Progressive web app (#367)
* Basic PWA support * Theme color * Removed manifest reference added by angular cli * Added update notification * Basic install widget * Fixed annoying scrolling bug on mobile * Minor fixes * Minor tweaks * Better platform detection * iOS instructions * Success notification and viewport styling * Styling * Dark bg color * Another color change * Yet another color change * Small tweaks to update/install UX * Styling * Bugfix * Several Install widget fixes * Updated angular service-worker * Changed install widget * Caching strategies * Linting * Styling * PR comments
This commit is contained in:
		
					parent
					
						
							
								74d4907be2
							
						
					
				
			
			
				commit
				
					
						5cca259ae7
					
				
			
		
					 16 changed files with 391 additions and 39 deletions
				
			
		
							
								
								
									
										10
									
								
								angular.json
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								angular.json
									
										
									
									
									
								
							| 
						 | 
					@ -20,7 +20,8 @@
 | 
				
			||||||
            "assets": [
 | 
					            "assets": [
 | 
				
			||||||
              "src/assets",
 | 
					              "src/assets",
 | 
				
			||||||
              "src/pow.wasm",
 | 
					              "src/pow.wasm",
 | 
				
			||||||
              "src/404.html"
 | 
					              "src/404.html",
 | 
				
			||||||
 | 
					              "src/manifest.webmanifest"
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "styles": [
 | 
					            "styles": [
 | 
				
			||||||
              "src/styles.less"
 | 
					              "src/styles.less"
 | 
				
			||||||
| 
						 | 
					@ -71,7 +72,9 @@
 | 
				
			||||||
                  "replace": "src/environments/environment.ts",
 | 
					                  "replace": "src/environments/environment.ts",
 | 
				
			||||||
                  "with": "src/environments/environment.prod.ts"
 | 
					                  "with": "src/environments/environment.prod.ts"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              ]
 | 
					              ],
 | 
				
			||||||
 | 
					              "serviceWorker": true,
 | 
				
			||||||
 | 
					              "ngswConfigPath": "ngsw-config.json"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "desktop": {
 | 
					            "desktop": {
 | 
				
			||||||
              "budgets": [
 | 
					              "budgets": [
 | 
				
			||||||
| 
						 | 
					@ -131,7 +134,8 @@
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "assets": [
 | 
					            "assets": [
 | 
				
			||||||
              "src/assets",
 | 
					              "src/assets",
 | 
				
			||||||
              "src/pow.wasm"
 | 
					              "src/pow.wasm",
 | 
				
			||||||
 | 
					              "src/manifest.webmanifest"
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										50
									
								
								ngsw-config.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								ngsw-config.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,50 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
 | 
				
			||||||
 | 
					  "index": "/index.html",
 | 
				
			||||||
 | 
					  "assetGroups": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "app",
 | 
				
			||||||
 | 
					      "installMode": "prefetch",
 | 
				
			||||||
 | 
					      "resources": {
 | 
				
			||||||
 | 
					        "files": [
 | 
				
			||||||
 | 
					          "/favicon.ico",
 | 
				
			||||||
 | 
					          "/index.html",
 | 
				
			||||||
 | 
					          "/manifest.webmanifest",
 | 
				
			||||||
 | 
					          "/*.css",
 | 
				
			||||||
 | 
					          "/*.js"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "assets",
 | 
				
			||||||
 | 
					      "installMode": "lazy",
 | 
				
			||||||
 | 
					      "updateMode": "prefetch",
 | 
				
			||||||
 | 
					      "resources": {
 | 
				
			||||||
 | 
					        "files": [
 | 
				
			||||||
 | 
					          "/assets/**",
 | 
				
			||||||
 | 
					          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "dataGroups": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "coingecko",
 | 
				
			||||||
 | 
					      "urls": ["https://api.coingecko.com/**"],
 | 
				
			||||||
 | 
					      "cacheConfig": {
 | 
				
			||||||
 | 
					        "maxSize": 3,
 | 
				
			||||||
 | 
					        "maxAge": "60d",
 | 
				
			||||||
 | 
					        "strategy": "freshness"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "ninja",
 | 
				
			||||||
 | 
					      "urls": ["https://mynano.ninja/api/**"],
 | 
				
			||||||
 | 
					      "cacheConfig": {
 | 
				
			||||||
 | 
					        "maxSize": 50,
 | 
				
			||||||
 | 
					        "maxAge": "60d",
 | 
				
			||||||
 | 
					        "strategy": "freshness"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										64
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										64
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -816,6 +816,14 @@
 | 
				
			||||||
        "tslib": "^2.0.0"
 | 
					        "tslib": "^2.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "@angular/service-worker": {
 | 
				
			||||||
 | 
					      "version": "10.2.5",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-10.2.5.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-8gsI+sg84Oor83w2iyQ99Tmf3sEXXiLT9R/kJ0NuOzRkPW0GV//Hi0y1emTpnp+INzYlCgqRBdp45HlDnynYOA==",
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "tslib": "^2.0.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "@babel/code-frame": {
 | 
					    "@babel/code-frame": {
 | 
				
			||||||
      "version": "7.10.4",
 | 
					      "version": "7.10.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
 | 
				
			||||||
| 
						 | 
					@ -2367,7 +2375,7 @@
 | 
				
			||||||
    "@types/jasmine": {
 | 
					    "@types/jasmine": {
 | 
				
			||||||
      "version": "2.5.54",
 | 
					      "version": "2.5.54",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.54.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.54.tgz",
 | 
				
			||||||
      "integrity": "sha512-B9YofFbUljs19g5gBKUYeLIulsh31U5AK70F41BImQRHEZQGm4GcN922UvnYwkduMqbC/NH+9fruWa/zrqvHIg==",
 | 
					      "integrity": "sha1-prXyrir7bgMHd06MfGCOA31JHGM=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "@types/jasminewd2": {
 | 
					    "@types/jasminewd2": {
 | 
				
			||||||
| 
						 | 
					@ -2415,7 +2423,7 @@
 | 
				
			||||||
    "@types/qrcode": {
 | 
					    "@types/qrcode": {
 | 
				
			||||||
      "version": "0.8.1",
 | 
					      "version": "0.8.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-0.8.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-0.8.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-Z3Z5S+DS9vBGwH0wBN4544se8ogM5Y0+t7flmPxvhR4nj7zTvOy3PkNaCX5vwKXOgr6KeLfDEX5lW4fTZ+chIg==",
 | 
					      "integrity": "sha1-V3bLXaKZz6fO4mEPWZl6ytkK040=",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "@types/node": "*"
 | 
					        "@types/node": "*"
 | 
				
			||||||
| 
						 | 
					@ -2933,7 +2941,7 @@
 | 
				
			||||||
    "ansi-styles": {
 | 
					    "ansi-styles": {
 | 
				
			||||||
      "version": "3.2.1",
 | 
					      "version": "3.2.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
 | 
					      "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "color-convert": "^1.9.0"
 | 
					        "color-convert": "^1.9.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -3020,12 +3028,12 @@
 | 
				
			||||||
    "aproba": {
 | 
					    "aproba": {
 | 
				
			||||||
      "version": "1.2.0",
 | 
					      "version": "1.2.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
 | 
					      "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "are-we-there-yet": {
 | 
					    "are-we-there-yet": {
 | 
				
			||||||
      "version": "1.1.5",
 | 
					      "version": "1.1.5",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
 | 
				
			||||||
      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
 | 
					      "integrity": "sha1-SzXClE8GKov82mZBB2A1D+nd/CE=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "delegates": "^1.0.0",
 | 
					        "delegates": "^1.0.0",
 | 
				
			||||||
        "readable-stream": "^2.0.6"
 | 
					        "readable-stream": "^2.0.6"
 | 
				
			||||||
| 
						 | 
					@ -3034,7 +3042,7 @@
 | 
				
			||||||
    "argparse": {
 | 
					    "argparse": {
 | 
				
			||||||
      "version": "1.0.10",
 | 
					      "version": "1.0.10",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
 | 
				
			||||||
      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
 | 
					      "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "sprintf-js": "~1.0.2"
 | 
					        "sprintf-js": "~1.0.2"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -3188,7 +3196,7 @@
 | 
				
			||||||
    "async-exit-hook": {
 | 
					    "async-exit-hook": {
 | 
				
			||||||
      "version": "2.0.1",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==",
 | 
					      "integrity": "sha1-i9iwJLDsmxwBzMua+dspvXF9+vM=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "async-limiter": {
 | 
					    "async-limiter": {
 | 
				
			||||||
| 
						 | 
					@ -3463,7 +3471,7 @@
 | 
				
			||||||
    "bignumber.js": {
 | 
					    "bignumber.js": {
 | 
				
			||||||
      "version": "5.0.0",
 | 
					      "version": "5.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-5.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-5.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg=="
 | 
					      "integrity": "sha1-+85j8Jd2swAKgxhbrc3lJdrzSDM="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "binary-extensions": {
 | 
					    "binary-extensions": {
 | 
				
			||||||
      "version": "2.1.0",
 | 
					      "version": "2.1.0",
 | 
				
			||||||
| 
						 | 
					@ -3754,7 +3762,7 @@
 | 
				
			||||||
    "brace-expansion": {
 | 
					    "brace-expansion": {
 | 
				
			||||||
      "version": "1.1.11",
 | 
					      "version": "1.1.11",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 | 
				
			||||||
      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
 | 
					      "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "balanced-match": "^1.0.0",
 | 
					        "balanced-match": "^1.0.0",
 | 
				
			||||||
        "concat-map": "0.0.1"
 | 
					        "concat-map": "0.0.1"
 | 
				
			||||||
| 
						 | 
					@ -3908,7 +3916,7 @@
 | 
				
			||||||
    "buffer-alloc": {
 | 
					    "buffer-alloc": {
 | 
				
			||||||
      "version": "1.2.0",
 | 
					      "version": "1.2.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
 | 
					      "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "buffer-alloc-unsafe": "^1.1.0",
 | 
					        "buffer-alloc-unsafe": "^1.1.0",
 | 
				
			||||||
        "buffer-fill": "^1.0.0"
 | 
					        "buffer-fill": "^1.0.0"
 | 
				
			||||||
| 
						 | 
					@ -3917,7 +3925,7 @@
 | 
				
			||||||
    "buffer-alloc-unsafe": {
 | 
					    "buffer-alloc-unsafe": {
 | 
				
			||||||
      "version": "1.1.0",
 | 
					      "version": "1.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
 | 
					      "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "buffer-crc32": {
 | 
					    "buffer-crc32": {
 | 
				
			||||||
      "version": "0.2.13",
 | 
					      "version": "0.2.13",
 | 
				
			||||||
| 
						 | 
					@ -4301,7 +4309,7 @@
 | 
				
			||||||
    "cipher-base": {
 | 
					    "cipher-base": {
 | 
				
			||||||
      "version": "1.0.4",
 | 
					      "version": "1.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
 | 
					      "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "inherits": "^2.0.1",
 | 
					        "inherits": "^2.0.1",
 | 
				
			||||||
        "safe-buffer": "^5.0.1"
 | 
					        "safe-buffer": "^5.0.1"
 | 
				
			||||||
| 
						 | 
					@ -4774,7 +4782,7 @@
 | 
				
			||||||
    "content-type": {
 | 
					    "content-type": {
 | 
				
			||||||
      "version": "1.0.4",
 | 
					      "version": "1.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
 | 
					      "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "convert-source-map": {
 | 
					    "convert-source-map": {
 | 
				
			||||||
| 
						 | 
					@ -5411,7 +5419,7 @@
 | 
				
			||||||
    "deep-extend": {
 | 
					    "deep-extend": {
 | 
				
			||||||
      "version": "0.6.0",
 | 
					      "version": "0.6.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
 | 
					      "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "default-gateway": {
 | 
					    "default-gateway": {
 | 
				
			||||||
      "version": "4.2.0",
 | 
					      "version": "4.2.0",
 | 
				
			||||||
| 
						 | 
					@ -5627,7 +5635,7 @@
 | 
				
			||||||
    "diff": {
 | 
					    "diff": {
 | 
				
			||||||
      "version": "3.5.0",
 | 
					      "version": "3.5.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
 | 
					      "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "diffie-hellman": {
 | 
					    "diffie-hellman": {
 | 
				
			||||||
| 
						 | 
					@ -7152,7 +7160,7 @@
 | 
				
			||||||
    "fs-constants": {
 | 
					    "fs-constants": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
 | 
					      "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "fs-extra": {
 | 
					    "fs-extra": {
 | 
				
			||||||
      "version": "9.0.1",
 | 
					      "version": "9.0.1",
 | 
				
			||||||
| 
						 | 
					@ -8107,7 +8115,7 @@
 | 
				
			||||||
    "ini": {
 | 
					    "ini": {
 | 
				
			||||||
      "version": "1.3.5",
 | 
					      "version": "1.3.5",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
 | 
				
			||||||
      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
 | 
					      "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "inquirer": {
 | 
					    "inquirer": {
 | 
				
			||||||
      "version": "7.1.0",
 | 
					      "version": "7.1.0",
 | 
				
			||||||
| 
						 | 
					@ -9742,7 +9750,7 @@
 | 
				
			||||||
    "minimatch": {
 | 
					    "minimatch": {
 | 
				
			||||||
      "version": "3.0.4",
 | 
					      "version": "3.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
 | 
					      "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "brace-expansion": "^1.1.7"
 | 
					        "brace-expansion": "^1.1.7"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -10474,7 +10482,7 @@
 | 
				
			||||||
    "npmlog": {
 | 
					    "npmlog": {
 | 
				
			||||||
      "version": "4.1.2",
 | 
					      "version": "4.1.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
 | 
					      "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "are-we-there-yet": "~1.1.2",
 | 
					        "are-we-there-yet": "~1.1.2",
 | 
				
			||||||
        "console-control-strings": "~1.1.0",
 | 
					        "console-control-strings": "~1.1.0",
 | 
				
			||||||
| 
						 | 
					@ -12550,7 +12558,7 @@
 | 
				
			||||||
    "rc": {
 | 
					    "rc": {
 | 
				
			||||||
      "version": "1.2.8",
 | 
					      "version": "1.2.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
 | 
				
			||||||
      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
 | 
					      "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "deep-extend": "^0.6.0",
 | 
					        "deep-extend": "^0.6.0",
 | 
				
			||||||
        "ini": "~1.3.0",
 | 
					        "ini": "~1.3.0",
 | 
				
			||||||
| 
						 | 
					@ -13017,7 +13025,7 @@
 | 
				
			||||||
    "ripemd160": {
 | 
					    "ripemd160": {
 | 
				
			||||||
      "version": "2.0.2",
 | 
					      "version": "2.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
 | 
					      "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "hash-base": "^3.0.0",
 | 
					        "hash-base": "^3.0.0",
 | 
				
			||||||
        "inherits": "^2.0.1"
 | 
					        "inherits": "^2.0.1"
 | 
				
			||||||
| 
						 | 
					@ -13100,7 +13108,7 @@
 | 
				
			||||||
    "safe-buffer": {
 | 
					    "safe-buffer": {
 | 
				
			||||||
      "version": "5.1.2",
 | 
					      "version": "5.1.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
 | 
					      "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "safe-regex": {
 | 
					    "safe-regex": {
 | 
				
			||||||
      "version": "1.1.0",
 | 
					      "version": "1.1.0",
 | 
				
			||||||
| 
						 | 
					@ -13114,7 +13122,7 @@
 | 
				
			||||||
    "safer-buffer": {
 | 
					    "safer-buffer": {
 | 
				
			||||||
      "version": "2.1.2",
 | 
					      "version": "2.1.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
 | 
					      "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "sanitize-filename": {
 | 
					    "sanitize-filename": {
 | 
				
			||||||
      "version": "1.6.3",
 | 
					      "version": "1.6.3",
 | 
				
			||||||
| 
						 | 
					@ -13187,7 +13195,7 @@
 | 
				
			||||||
    "sax": {
 | 
					    "sax": {
 | 
				
			||||||
      "version": "1.2.4",
 | 
					      "version": "1.2.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
 | 
					      "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "schema-utils": {
 | 
					    "schema-utils": {
 | 
				
			||||||
      "version": "2.7.0",
 | 
					      "version": "2.7.0",
 | 
				
			||||||
| 
						 | 
					@ -14319,7 +14327,7 @@
 | 
				
			||||||
    "string_decoder": {
 | 
					    "string_decoder": {
 | 
				
			||||||
      "version": "1.1.1",
 | 
					      "version": "1.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
 | 
					      "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "safe-buffer": "~5.1.0"
 | 
					        "safe-buffer": "~5.1.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -15279,7 +15287,7 @@
 | 
				
			||||||
    "uri-js": {
 | 
					    "uri-js": {
 | 
				
			||||||
      "version": "4.2.2",
 | 
					      "version": "4.2.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
 | 
					      "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "punycode": "^2.1.0"
 | 
					        "punycode": "^2.1.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -16439,7 +16447,7 @@
 | 
				
			||||||
    "which": {
 | 
					    "which": {
 | 
				
			||||||
      "version": "1.3.1",
 | 
					      "version": "1.3.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
 | 
					      "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "isexe": "^2.0.0"
 | 
					        "isexe": "^2.0.0"
 | 
				
			||||||
| 
						 | 
					@ -16458,7 +16466,7 @@
 | 
				
			||||||
    "wide-align": {
 | 
					    "wide-align": {
 | 
				
			||||||
      "version": "1.1.3",
 | 
					      "version": "1.1.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
 | 
				
			||||||
      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
 | 
					      "integrity": "sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "string-width": "^1.0.2 || 2"
 | 
					        "string-width": "^1.0.2 || 2"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,7 @@
 | 
				
			||||||
    "@angular/platform-browser": "^10.0.7",
 | 
					    "@angular/platform-browser": "^10.0.7",
 | 
				
			||||||
    "@angular/platform-browser-dynamic": "^10.0.7",
 | 
					    "@angular/platform-browser-dynamic": "^10.0.7",
 | 
				
			||||||
    "@angular/router": "^10.0.7",
 | 
					    "@angular/router": "^10.0.7",
 | 
				
			||||||
 | 
					    "@angular/service-worker": "^10.2.5",
 | 
				
			||||||
    "@ledgerhq/hw-transport": "^5.39.0",
 | 
					    "@ledgerhq/hw-transport": "^5.39.0",
 | 
				
			||||||
    "@ledgerhq/hw-transport-node-ble": "^5.39.0",
 | 
					    "@ledgerhq/hw-transport-node-ble": "^5.39.0",
 | 
				
			||||||
    "@ledgerhq/hw-transport-node-hid": "^5.39.0",
 | 
					    "@ledgerhq/hw-transport-node-hid": "^5.39.0",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -224,6 +224,8 @@
 | 
				
			||||||
          </li>
 | 
					          </li>
 | 
				
			||||||
        </ul>
 | 
					        </ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <app-install-widget></app-install-widget>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class="nav-search">
 | 
					        <div class="nav-search">
 | 
				
			||||||
          <form class="uk-search uk-search-default uk-width-1-1">
 | 
					          <form class="uk-search uk-search-default uk-width-1-1">
 | 
				
			||||||
            <a href="javascript:void(0)" (click)="performSearch()" class="uk-search-icon-flip" uk-search-icon></a>
 | 
					            <a href="javascript:void(0)" (click)="performSearch()" class="uk-search-icon-flip" uk-search-icon></a>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,12 +7,14 @@ import {PriceService} from './services/price.service';
 | 
				
			||||||
import {NotificationService} from './services/notification.service';
 | 
					import {NotificationService} from './services/notification.service';
 | 
				
			||||||
import {WorkPoolService} from './services/work-pool.service';
 | 
					import {WorkPoolService} from './services/work-pool.service';
 | 
				
			||||||
import {Router} from '@angular/router';
 | 
					import {Router} from '@angular/router';
 | 
				
			||||||
 | 
					import {SwUpdate} from '@angular/service-worker';
 | 
				
			||||||
import {RepresentativeService} from './services/representative.service';
 | 
					import {RepresentativeService} from './services/representative.service';
 | 
				
			||||||
import {NodeService} from './services/node.service';
 | 
					import {NodeService} from './services/node.service';
 | 
				
			||||||
import { DesktopService, LedgerService } from './services';
 | 
					import { DesktopService, LedgerService } from './services';
 | 
				
			||||||
import { environment } from 'environments/environment';
 | 
					import { environment } from 'environments/environment';
 | 
				
			||||||
import { DeeplinkService } from './services/deeplink.service';
 | 
					import { DeeplinkService } from './services/deeplink.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-root',
 | 
					  selector: 'app-root',
 | 
				
			||||||
  templateUrl: './app.component.html',
 | 
					  templateUrl: './app.component.html',
 | 
				
			||||||
| 
						 | 
					@ -29,6 +31,7 @@ export class AppComponent implements OnInit {
 | 
				
			||||||
    public nodeService: NodeService,
 | 
					    public nodeService: NodeService,
 | 
				
			||||||
    private representative: RepresentativeService,
 | 
					    private representative: RepresentativeService,
 | 
				
			||||||
    private router: Router,
 | 
					    private router: Router,
 | 
				
			||||||
 | 
					    public updates: SwUpdate,
 | 
				
			||||||
    private workPool: WorkPoolService,
 | 
					    private workPool: WorkPoolService,
 | 
				
			||||||
    public price: PriceService,
 | 
					    public price: PriceService,
 | 
				
			||||||
    private desktop: DesktopService,
 | 
					    private desktop: DesktopService,
 | 
				
			||||||
| 
						 | 
					@ -48,7 +51,6 @@ export class AppComponent implements OnInit {
 | 
				
			||||||
  nanoPrice = this.price.price;
 | 
					  nanoPrice = this.price.price;
 | 
				
			||||||
  fiatTimeout = 5 * 60 * 1000; // Update fiat prices every 5 minutes
 | 
					  fiatTimeout = 5 * 60 * 1000; // Update fiat prices every 5 minutes
 | 
				
			||||||
  inactiveSeconds = 0;
 | 
					  inactiveSeconds = 0;
 | 
				
			||||||
  windowHeight = 1000;
 | 
					 | 
				
			||||||
  navExpanded = false;
 | 
					  navExpanded = false;
 | 
				
			||||||
  showAccountsDropdown = false;
 | 
					  showAccountsDropdown = false;
 | 
				
			||||||
  canToggleLightMode = true;
 | 
					  canToggleLightMode = true;
 | 
				
			||||||
| 
						 | 
					@ -144,6 +146,21 @@ export class AppComponent implements OnInit {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    this.desktop.send('deeplink-ready');
 | 
					    this.desktop.send('deeplink-ready');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Notify user if service worker update is available
 | 
				
			||||||
 | 
					    this.updates.available.subscribe((event) => {
 | 
				
			||||||
 | 
					      console.log(`SW update available. Current: ${event.current.hash}. New: ${event.available.hash}`);
 | 
				
			||||||
 | 
					      this.notifications.sendInfo(
 | 
				
			||||||
 | 
					        'An update was installed in the background and will be applied on next launch. <a href="#" (click)="applySwUpdate()">Apply immediately</a>',
 | 
				
			||||||
 | 
					        { length: 10000 }
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Notify user after service worker was updated
 | 
				
			||||||
 | 
					    this.updates.activated.subscribe((event) => {
 | 
				
			||||||
 | 
					      console.log(`SW update successful. Current: ${event.current.hash}`);
 | 
				
			||||||
 | 
					      this.notifications.sendSuccess('Nault was updated successfully.');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check how long the wallet has been inactive, and lock it if it's been too long
 | 
					    // Check how long the wallet has been inactive, and lock it if it's been too long
 | 
				
			||||||
    setInterval(() => {
 | 
					    setInterval(() => {
 | 
				
			||||||
      this.inactiveSeconds += 1;
 | 
					      this.inactiveSeconds += 1;
 | 
				
			||||||
| 
						 | 
					@ -180,6 +197,10 @@ export class AppComponent implements OnInit {
 | 
				
			||||||
    this.settings.setAppSetting('walletVersion', 2); // Update wallet version so we do not patch in the future.
 | 
					    this.settings.setAppSetting('walletVersion', 2); // Update wallet version so we do not patch in the future.
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  applySwUpdate() {
 | 
				
			||||||
 | 
					    this.updates.activateUpdate();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  toggleNav() {
 | 
					  toggleNav() {
 | 
				
			||||||
    this.navExpanded = !this.navExpanded;
 | 
					    this.navExpanded = !this.navExpanded;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,6 +53,7 @@ import { QrScanComponent } from './components/qr-scan/qr-scan.component';
 | 
				
			||||||
import {SignComponent} from './components/sign/sign.component';
 | 
					import {SignComponent} from './components/sign/sign.component';
 | 
				
			||||||
import {RemoteSigningComponent} from './components/remote-signing/remote-signing.component';
 | 
					import {RemoteSigningComponent} from './components/remote-signing/remote-signing.component';
 | 
				
			||||||
import {RemoteSignService} from './services/remote-sign.service';
 | 
					import {RemoteSignService} from './services/remote-sign.service';
 | 
				
			||||||
 | 
					import { InstallWidgetComponent } from './components/install-widget/install-widget.component';
 | 
				
			||||||
import { QrModalComponent } from './components/qr-modal/qr-modal.component';
 | 
					import { QrModalComponent } from './components/qr-modal/qr-modal.component';
 | 
				
			||||||
import { QrModalService } from './services/qr-modal.service';
 | 
					import { QrModalService } from './services/qr-modal.service';
 | 
				
			||||||
import { NgbModule, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
 | 
					import { NgbModule, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
 | 
				
			||||||
| 
						 | 
					@ -64,6 +65,8 @@ import { ZXingScannerModule } from '@zxing/ngx-scanner';
 | 
				
			||||||
import { DeeplinkService, NinjaService } from './services';
 | 
					import { DeeplinkService, NinjaService } from './services';
 | 
				
			||||||
import { ConverterComponent } from './components/converter/converter.component';
 | 
					import { ConverterComponent } from './components/converter/converter.component';
 | 
				
			||||||
import { QrGeneratorComponent } from './components/qr-generator/qr-generator.component';
 | 
					import { QrGeneratorComponent } from './components/qr-generator/qr-generator.component';
 | 
				
			||||||
 | 
					import { ServiceWorkerModule } from '@angular/service-worker';
 | 
				
			||||||
 | 
					import { environment } from '../environments/environment';
 | 
				
			||||||
import { MultisigComponent } from './components/multisig/multisig.component';
 | 
					import { MultisigComponent } from './components/multisig/multisig.component';
 | 
				
			||||||
import { KeygeneratorComponent } from './components/keygenerator/keygenerator.component';
 | 
					import { KeygeneratorComponent } from './components/keygenerator/keygenerator.component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,6 +105,7 @@ import { KeygeneratorComponent } from './components/keygenerator/keygenerator.co
 | 
				
			||||||
    QrModalComponent,
 | 
					    QrModalComponent,
 | 
				
			||||||
    ConverterComponent,
 | 
					    ConverterComponent,
 | 
				
			||||||
    QrGeneratorComponent,
 | 
					    QrGeneratorComponent,
 | 
				
			||||||
 | 
					    InstallWidgetComponent,
 | 
				
			||||||
    MultisigComponent,
 | 
					    MultisigComponent,
 | 
				
			||||||
    KeygeneratorComponent,
 | 
					    KeygeneratorComponent,
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
| 
						 | 
					@ -115,6 +119,7 @@ import { KeygeneratorComponent } from './components/keygenerator/keygenerator.co
 | 
				
			||||||
    ZXingScannerModule,
 | 
					    ZXingScannerModule,
 | 
				
			||||||
    NgbModule,
 | 
					    NgbModule,
 | 
				
			||||||
    PasswordStrengthMeterModule,
 | 
					    PasswordStrengthMeterModule,
 | 
				
			||||||
 | 
					    ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  providers: [
 | 
					  providers: [
 | 
				
			||||||
    UtilService,
 | 
					    UtilService,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					<div (click)="install()" [tabindex]="isIosInstallable() ? -1 : 0" class="nav-install-row half-muted" [class.interactable]="!isIosInstallable()" [class.large]="isIosInstallable()" [class.visible]="showInstallPromotion" [class.uk-hidden]="!isPromotable()">
 | 
				
			||||||
 | 
					    <span uk-icon="icon: download; ratio: 1.2" class="icon"></span>
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					        <div class="label">Install Nault for {{ platform }}</div>
 | 
				
			||||||
 | 
					        <div class="description" *ngIf="isIosInstallable()">
 | 
				
			||||||
 | 
					            1. Tap the <span uk-icon="icon: push; ratio: 0.8"></span> Share button 
 | 
				
			||||||
 | 
					            <span *ngIf="platform === 'iOS'">below</span>
 | 
				
			||||||
 | 
					            <span *ngIf="platform === 'iPadOS'">in the top right</span> <br/>
 | 
				
			||||||
 | 
					            2. Select <span uk-icon="icon: plus-circle; ratio: 0.8"></span> Add to home screen
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,50 @@
 | 
				
			||||||
 | 
					.nav-install-row {
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    height: 65px;
 | 
				
			||||||
 | 
					    border-bottom: 1px solid #16161b;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    box-sizing: border-box;
 | 
				
			||||||
 | 
					    padding: 0 20px;
 | 
				
			||||||
 | 
					    color: white;
 | 
				
			||||||
 | 
					    transition: all 1s ease-in-out;
 | 
				
			||||||
 | 
					    font-family: Montserrat, Arial, Helvetica, sans-serif;
 | 
				
			||||||
 | 
					    outline: none;
 | 
				
			||||||
 | 
					    overflow: hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &.half-muted {
 | 
				
			||||||
 | 
					        color: #b6bed5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        &.interactable:hover .label {
 | 
				
			||||||
 | 
					            border-color: #b6bed5;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &.interactable {
 | 
				
			||||||
 | 
					        text-decoration: none;
 | 
				
			||||||
 | 
					        cursor: pointer;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &.large {
 | 
				
			||||||
 | 
					        height: 90px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .label {
 | 
				
			||||||
 | 
					        border-bottom: 2px solid transparent;
 | 
				
			||||||
 | 
					        transition: border-color .1s ease-in-out;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .description {
 | 
				
			||||||
 | 
					        color: #8f8fab;
 | 
				
			||||||
 | 
					        font-size: 0.875rem;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .icon {
 | 
				
			||||||
 | 
					        margin-right: 8px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &:not(.visible) {
 | 
				
			||||||
 | 
					        height: 0;
 | 
				
			||||||
 | 
					        opacity: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { InstallWidgetComponent } from './install-widget.component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('InstallWidgetComponent', () => {
 | 
				
			||||||
 | 
					  let component: InstallWidgetComponent;
 | 
				
			||||||
 | 
					  let fixture: ComponentFixture<InstallWidgetComponent>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(async(() => {
 | 
				
			||||||
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
 | 
					      declarations: [ InstallWidgetComponent ]
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .compileComponents();
 | 
				
			||||||
 | 
					  }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(() => {
 | 
				
			||||||
 | 
					    fixture = TestBed.createComponent(InstallWidgetComponent);
 | 
				
			||||||
 | 
					    component = fixture.componentInstance;
 | 
				
			||||||
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should create', () => {
 | 
				
			||||||
 | 
					    expect(component).toBeTruthy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										105
									
								
								src/app/components/install-widget/install-widget.component.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/app/components/install-widget/install-widget.component.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,105 @@
 | 
				
			||||||
 | 
					import { Component, OnInit } from '@angular/core';
 | 
				
			||||||
 | 
					import { NotificationService } from 'app/services/notification.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface InstallEvent extends Event {
 | 
				
			||||||
 | 
					  userChoice: Promise<{ outcome: 'accepted' | 'dismissed', platform: string }>;
 | 
				
			||||||
 | 
					  prompt(): void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					  selector: 'app-install-widget',
 | 
				
			||||||
 | 
					  templateUrl: './install-widget.component.html',
 | 
				
			||||||
 | 
					  styleUrls: ['./install-widget.component.less'],
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class InstallWidgetComponent implements OnInit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  installEvent: InstallEvent;
 | 
				
			||||||
 | 
					  showInstallPromotion = false;
 | 
				
			||||||
 | 
					  platform = this.getPlatform();
 | 
				
			||||||
 | 
					  promotablePlatforms = ['Android', 'iOS', 'iPadOS', 'Chrome OS'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(
 | 
				
			||||||
 | 
					    private notifications: NotificationService,
 | 
				
			||||||
 | 
					  ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ngOnInit() {
 | 
				
			||||||
 | 
					    if (!this.isPromotable()) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Show clickable installation banner (Chrome / Edge only)
 | 
				
			||||||
 | 
					    window.addEventListener('beforeinstallprompt', (event: InstallEvent) => {
 | 
				
			||||||
 | 
					      // Prevent the mini-infobar from appearing on mobile
 | 
				
			||||||
 | 
					      event.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.installEvent = event;
 | 
				
			||||||
 | 
					      this.showInstallPromotion = true;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Fallback for iOS family
 | 
				
			||||||
 | 
					    if (this.isIosInstallable()) {
 | 
				
			||||||
 | 
					      setTimeout(() => {
 | 
				
			||||||
 | 
					        this.showInstallPromotion = true;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  install() {
 | 
				
			||||||
 | 
					    if (!this.installEvent) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.installEvent.prompt();
 | 
				
			||||||
 | 
					    this.installEvent.userChoice.then((result) => {
 | 
				
			||||||
 | 
					      if (result.outcome === 'accepted') {
 | 
				
			||||||
 | 
					        this.notifications.sendSuccess('Nault was successfully installed to the device.');
 | 
				
			||||||
 | 
					        this.dismiss();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dismiss() {
 | 
				
			||||||
 | 
					    this.showInstallPromotion = false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getPlatform() {
 | 
				
			||||||
 | 
					    const platform = window.navigator.platform;
 | 
				
			||||||
 | 
					    const userAgent = window.navigator.userAgent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (platform.includes('Win')) {
 | 
				
			||||||
 | 
					      return 'Windows';
 | 
				
			||||||
 | 
					    } else if (platform.includes('Mac')) {
 | 
				
			||||||
 | 
					      return 'Mac';
 | 
				
			||||||
 | 
					    } else if (userAgent.includes('Android')) {
 | 
				
			||||||
 | 
					      return 'Android';
 | 
				
			||||||
 | 
					    } else if (userAgent.includes('CrOS')) {
 | 
				
			||||||
 | 
					      return 'Chrome OS';
 | 
				
			||||||
 | 
					    } else if (platform.includes('Linux')) {
 | 
				
			||||||
 | 
					      return 'Linux';
 | 
				
			||||||
 | 
					    } else if (platform.includes('iPhone')) {
 | 
				
			||||||
 | 
					      return 'iOS';
 | 
				
			||||||
 | 
					    } else if (platform.includes('iPad')) {
 | 
				
			||||||
 | 
					      return 'iPadOS';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  isIosInstallable() {
 | 
				
			||||||
 | 
					    if (!this.isPromotable() || this.isInstalled()) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return this.platform === 'iOS' || this.platform === 'iPadOS' && 'standalone' in window.navigator;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  isPromotable() {
 | 
				
			||||||
 | 
					    if (this.isInstalled()) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return this.promotablePlatforms.includes(this.platform);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  isInstalled() {
 | 
				
			||||||
 | 
					    return window.matchMedia('(display-mode: standalone)').matches // Chrome & Edge
 | 
				
			||||||
 | 
					      || (window.navigator as any).standalone === true // Safari
 | 
				
			||||||
 | 
					      || window.navigator.userAgent.includes('Electron'); // Electron
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,8 @@
 | 
				
			||||||
            "type": "image/png"
 | 
					            "type": "image/png"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "theme_color": "#ffffff",
 | 
					    "theme_color": "#4a90e2",
 | 
				
			||||||
    "background_color": "#ffffff",
 | 
					    "background_color": "#1f1f24",
 | 
				
			||||||
    "display": "standalone"
 | 
					    "display": "standalone",
 | 
				
			||||||
 | 
					    "start_url": "/"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@
 | 
				
			||||||
  <meta name="application-name" content="Nault">
 | 
					  <meta name="application-name" content="Nault">
 | 
				
			||||||
  <meta name="msapplication-TileColor" content="#4a90e2">
 | 
					  <meta name="msapplication-TileColor" content="#4a90e2">
 | 
				
			||||||
  <meta name="msapplication-config" content="assets/favicon/browserconfig.xml">
 | 
					  <meta name="msapplication-config" content="assets/favicon/browserconfig.xml">
 | 
				
			||||||
  <meta name="theme-color" content="#ffffff">
 | 
					  <meta name="theme-color" content="#4a90e2">
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body class="body" style="margin: 0;">
 | 
					<body class="body" style="margin: 0;">
 | 
				
			||||||
  <app-root>
 | 
					  <app-root>
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,8 @@
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </app-root>
 | 
					  </app-root>
 | 
				
			||||||
  <script type="text/javascript" src="assets/lib/pow/startThreads.js" async></script>
 | 
					  <script type="text/javascript" src="assets/lib/pow/startThreads.js" async=""></script>
 | 
				
			||||||
  <script type="text/javascript" src="assets/lib/pow/nano-webgl-pow.js" async></script>
 | 
					  <script type="text/javascript" src="assets/lib/pow/nano-webgl-pow.js" async=""></script>
 | 
				
			||||||
 | 
					  <noscript>Please enable JavaScript to continue using this application.</noscript>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,8 @@
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.nav-container {
 | 
					.nav-container {
 | 
				
			||||||
 | 
						display: flex;
 | 
				
			||||||
 | 
						flex-direction: column;
 | 
				
			||||||
	background: @nav-background-color;
 | 
						background: @nav-background-color;
 | 
				
			||||||
	color: #868AB0;
 | 
						color: #868AB0;
 | 
				
			||||||
	padding-left: 0;
 | 
						padding-left: 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,10 @@ h1, h2, h3, h4, h5, .uk-text-lead, .uk-button, .uk-alert, .uk-description-list d
 | 
				
			||||||
	border-radius: @global-border-radius-medium;
 | 
						border-radius: @global-border-radius-medium;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* {
 | 
				
			||||||
 | 
					    -webkit-tap-highlight-color: rgba(0,0,0,0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
@media (max-width: 939px) {
 | 
					@media (max-width: 939px) {
 | 
				
			||||||
	.nlt-button-group button {
 | 
						.nlt-button-group button {
 | 
				
			||||||
		margin-bottom: @nlt-intro-margin / 2 !important;
 | 
							margin-bottom: @nlt-intro-margin / 2 !important;
 | 
				
			||||||
| 
						 | 
					@ -195,12 +199,14 @@ input[type=number] {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.app-grid {
 | 
					.app-grid {
 | 
				
			||||||
 | 
						// position: relative;
 | 
				
			||||||
	margin-top: 0;
 | 
						margin-top: 0;
 | 
				
			||||||
	overflow: hidden;
 | 
						overflow: hidden;
 | 
				
			||||||
	margin-left: 0;
 | 
						margin-left: 0;
 | 
				
			||||||
	height: 100vh;
 | 
						height: 100vh;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.content-container {
 | 
					.content-container {
 | 
				
			||||||
	background: #FFF;
 | 
						background: #FFF;
 | 
				
			||||||
	padding: 15px 20px;
 | 
						padding: 15px 20px;
 | 
				
			||||||
| 
						 | 
					@ -217,7 +223,7 @@ input[type=number] {
 | 
				
			||||||
		margin-top: @mobile-top-bar-height;
 | 
							margin-top: @mobile-top-bar-height;
 | 
				
			||||||
		height: calc(100vh - @mobile-top-bar-height);
 | 
							height: calc(100vh - @mobile-top-bar-height);
 | 
				
			||||||
		padding: 15px 15px;
 | 
							padding: 15px 15px;
 | 
				
			||||||
		transition: transform 0.5s ease;
 | 
							transition: transform 0.3s ease;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		&.nav-expanded {
 | 
							&.nav-expanded {
 | 
				
			||||||
			transform: translateX(360px);
 | 
								transform: translateX(360px);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										59
									
								
								src/manifest.webmanifest
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/manifest.webmanifest
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,59 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "nault",
 | 
				
			||||||
 | 
					  "short_name": "nault",
 | 
				
			||||||
 | 
					  "theme_color": "#1976d2",
 | 
				
			||||||
 | 
					  "background_color": "#1f1f24",
 | 
				
			||||||
 | 
					  "display": "standalone",
 | 
				
			||||||
 | 
					  "scope": "./",
 | 
				
			||||||
 | 
					  "start_url": "./",
 | 
				
			||||||
 | 
					  "icons": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "assets/icons/icon-72x72.png",
 | 
				
			||||||
 | 
					      "sizes": "72x72",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "maskable any"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "assets/icons/icon-96x96.png",
 | 
				
			||||||
 | 
					      "sizes": "96x96",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "maskable any"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "assets/icons/icon-128x128.png",
 | 
				
			||||||
 | 
					      "sizes": "128x128",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "maskable any"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "assets/icons/icon-144x144.png",
 | 
				
			||||||
 | 
					      "sizes": "144x144",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "maskable any"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "assets/icons/icon-152x152.png",
 | 
				
			||||||
 | 
					      "sizes": "152x152",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "maskable any"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "assets/icons/icon-192x192.png",
 | 
				
			||||||
 | 
					      "sizes": "192x192",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "maskable any"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "assets/icons/icon-384x384.png",
 | 
				
			||||||
 | 
					      "sizes": "384x384",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "maskable any"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "assets/icons/icon-512x512.png",
 | 
				
			||||||
 | 
					      "sizes": "512x512",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "maskable any"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue