├── .github └── workflows │ └── release.yml ├── .gitignore ├── .vscode └── extensions.json ├── LICENSE ├── README.md ├── angular.json ├── app-icon.png ├── electron ├── .editorconfig ├── .eslintrc.json ├── .github │ └── workflows │ │ ├── clean-artifacts.yml │ │ └── windows.yml ├── .gitignore ├── .npmrc ├── .vscode │ ├── launch.json │ └── tasks.json ├── LICENSE ├── README.md ├── _config.yml ├── angular.json ├── angular.webpack.js ├── data │ ├── icon-no-bg-small.png │ ├── icon-no-bg.png │ └── icon.png ├── e2e │ ├── common-setup.ts │ ├── main.e2e.ts │ └── tsconfig.e2e.json ├── electron-builder.json ├── ionic.config.json ├── main.ts ├── package-lock.json ├── package.json ├── scripts │ ├── copy-file-mac.js │ ├── copy-file.js │ ├── fix.script.js │ └── version.script.js ├── src │ ├── app │ │ ├── app-routing.module.ts │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ └── core │ │ │ ├── core.module.ts │ │ │ └── services │ │ │ ├── app.service.ts │ │ │ ├── command.service.ts │ │ │ ├── electron.service.ts │ │ │ ├── settings.service.ts │ │ │ └── storage.service.ts │ ├── assets │ │ ├── .gitkeep │ │ ├── animations │ │ │ ├── 3927-qr-scan.json │ │ │ ├── 9953-loading-round.json │ │ │ ├── bell-green.json │ │ │ ├── bell-white.json │ │ │ ├── lf30_editor_PsHnfk.json │ │ │ └── ring.json │ │ ├── background.jpg │ │ ├── i18n │ │ │ ├── de.json │ │ │ └── en.json │ │ ├── icons │ │ │ ├── DE.png │ │ │ ├── US.png │ │ │ ├── favicon.256x256.png │ │ │ ├── favicon.512x512.png │ │ │ ├── favicon.ico │ │ │ └── favicon.png │ │ └── images │ │ │ ├── be.png │ │ │ └── screen-recording.png │ ├── environments │ │ ├── environment.dev.ts │ │ ├── environment.prod.ts │ │ ├── environment.ts │ │ └── environment.web.ts │ ├── index.html │ ├── karma.conf.js │ ├── main.ts │ ├── pages │ │ ├── home │ │ │ ├── home-routing.module.ts │ │ │ ├── home.module.ts │ │ │ ├── home.page.html │ │ │ ├── home.page.scss │ │ │ ├── home.page.spec.ts │ │ │ ├── home.page.ts │ │ │ ├── lazyFor.directive.ts │ │ │ └── number.directive.ts │ │ └── settings │ │ │ ├── settings-routing.module.ts │ │ │ ├── settings.module.ts │ │ │ ├── settings.page.html │ │ │ ├── settings.page.scss │ │ │ ├── settings.page.spec.ts │ │ │ └── settings.page.ts │ ├── polyfills-test.ts │ ├── polyfills.ts │ ├── styles.scss │ ├── test.ts │ ├── tsconfig.app.json │ ├── tsconfig.spec.json │ └── typings.d.ts ├── tailwind.config.js ├── tsconfig.json └── tsconfig.serve.json ├── package.json ├── src-tauri ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── build.rs ├── icons │ ├── 128x128.png │ ├── 128x128@2x.png │ ├── 32x32.png │ ├── Square107x107Logo.png │ ├── Square142x142Logo.png │ ├── Square150x150Logo.png │ ├── Square284x284Logo.png │ ├── Square30x30Logo.png │ ├── Square310x310Logo.png │ ├── Square44x44Logo.png │ ├── Square71x71Logo.png │ ├── Square89x89Logo.png │ ├── StoreLogo.png │ ├── icon.icns │ ├── icon.ico │ └── icon.png ├── src │ └── main.rs └── tauri.conf.json ├── src ├── app │ └── app.component.ts ├── assets │ ├── angular.svg │ └── tauri.svg ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── index.html ├── main.ts ├── polyfills.ts └── style.css ├── stuff ├── icon.sketch └── logo.psd ├── tailwind.config.cjs ├── tsconfig.app.json ├── tsconfig.json └── yarn.lock /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Release" 2 | 3 | on: 4 | create: 5 | tags: 6 | - "*" 7 | 8 | jobs: 9 | create-release: 10 | runs-on: ubuntu-20.04 11 | outputs: 12 | release_id: ${{ steps.create-release.outputs.result }} 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: setup node 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: 16 20 | - name: get version 21 | run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV 22 | - name: create release 23 | id: create-release 24 | uses: actions/github-script@v6 25 | with: 26 | script: | 27 | const { data } = await github.rest.repos.createRelease({ 28 | owner: context.repo.owner, 29 | repo: context.repo.repo, 30 | tag_name: `app-v${process.env.PACKAGE_VERSION}`, 31 | name: `Desktop App v${process.env.PACKAGE_VERSION}`, 32 | body: 'Take a look at the assets to download and install this app.', 33 | draft: true, 34 | prerelease: false 35 | }) 36 | 37 | return data.id 38 | 39 | build-tauri: 40 | needs: create-release 41 | strategy: 42 | fail-fast: false 43 | matrix: 44 | platform: [windows-latest] 45 | 46 | runs-on: ${{ matrix.platform }} 47 | steps: 48 | - uses: actions/checkout@v3 49 | - name: setup node 50 | uses: actions/setup-node@v3 51 | with: 52 | node-version: 16 53 | - name: install Rust stable 54 | uses: dtolnay/rust-toolchain@stable 55 | - name: install app dependencies and build it 56 | run: yarn && yarn build 57 | - uses: tauri-apps/tauri-action@v0 58 | env: 59 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 60 | with: 61 | releaseId: ${{ needs.create-release.outputs.release_id }} 62 | 63 | publish-release: 64 | runs-on: ubuntu-latest 65 | needs: [create-release, build-tauri] 66 | 67 | steps: 68 | - name: publish release 69 | id: publish-release 70 | uses: actions/github-script@v6 71 | env: 72 | release_id: ${{ needs.create-release.outputs.release_id }} 73 | with: 74 | script: | 75 | github.rest.repos.updateRelease({ 76 | owner: context.repo.owner, 77 | repo: context.repo.repo, 78 | release_id: process.env.release_id, 79 | draft: false, 80 | prerelease: false 81 | }) 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | .angular 15 | 16 | # Editor directories and files 17 | .vscode/* 18 | !.vscode/extensions.json 19 | .idea 20 | .DS_Store 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "tauri-apps.tauri-vscode", 4 | "rust-lang.rust-analyzer", 5 | "angular.ng-template" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # winget gui + installer 2 | 3 | Simple 2mb winget GUI 4 | 5 | * Only 2mb Download Size 6 | * Update / Uninstall / Install 7 | * Search 8 | * Winget Autoinstaller 9 | * Open Source / MIT 10 | 11 | [Download](https://github.com/codextde/winget-gui/releases/latest) 12 | 13 | ![image](https://user-images.githubusercontent.com/19570043/209976748-a20bbfdc-d3c6-4fa6-97dd-ceca14eb7a23.png) 14 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "cli": { 6 | "analytics": false 7 | }, 8 | "projects": { 9 | "winget-gui": { 10 | "projectType": "application", 11 | "root": "", 12 | "sourceRoot": "src", 13 | "prefix": "app", 14 | "architect": { 15 | "build": { 16 | "builder": "@angular-devkit/build-angular:browser", 17 | "options": { 18 | "outputPath": "dist/", 19 | "index": "src/index.html", 20 | "main": "src/main.ts", 21 | "polyfills": "src/polyfills.ts", 22 | "tsConfig": "tsconfig.app.json", 23 | "inlineStyleLanguage": "scss", 24 | "assets": ["src/favicon.ico", "src/assets"], 25 | "styles": ["src/style.css"], 26 | "scripts": [] 27 | }, 28 | "configurations": { 29 | "production": { 30 | "budgets": [ 31 | { 32 | "type": "initial", 33 | "maximumWarning": "500kb", 34 | "maximumError": "1mb" 35 | }, 36 | { 37 | "type": "anyComponentStyle", 38 | "maximumWarning": "2kb", 39 | "maximumError": "4kb" 40 | } 41 | ], 42 | "fileReplacements": [ 43 | { 44 | "replace": "src/environments/environment.ts", 45 | "with": "src/environments/environment.prod.ts" 46 | } 47 | ], 48 | "outputHashing": "all" 49 | }, 50 | "development": { 51 | "buildOptimizer": false, 52 | "optimization": false, 53 | "vendorChunk": true, 54 | "extractLicenses": false, 55 | "sourceMap": true, 56 | "namedChunks": true 57 | } 58 | }, 59 | "defaultConfiguration": "production" 60 | }, 61 | "serve": { 62 | "builder": "@angular-devkit/build-angular:dev-server", 63 | "configurations": { 64 | "production": { 65 | "browserTarget": "winget-gui:build:production" 66 | }, 67 | "development": { 68 | "browserTarget": "winget-gui:build:development" 69 | } 70 | }, 71 | "defaultConfiguration": "development" 72 | }, 73 | "extract-i18n": { 74 | "builder": "@angular-devkit/build-angular:extract-i18n", 75 | "options": { 76 | "browserTarget": "winget-gui:build" 77 | } 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/app-icon.png -------------------------------------------------------------------------------- /electron/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | quote_type = single 11 | 12 | [*.md] 13 | max_line_length = off 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /electron/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "es6": true, 6 | "es2017": true 7 | }, 8 | "overrides": [ 9 | { 10 | "files": ["*.ts"], 11 | "extends": [ 12 | "eslint:recommended", 13 | "plugin:@typescript-eslint/eslint-recommended", 14 | "plugin:@typescript-eslint/recommended", 15 | "plugin:@typescript-eslint/recommended-requiring-type-checking" 16 | ], 17 | "parser": "@typescript-eslint/parser", 18 | "parserOptions": { 19 | "ecmaVersion": 10, 20 | "project": [ 21 | "./tsconfig.serve.json", 22 | "./src/tsconfig.app.json", 23 | "./src/tsconfig.spec.json", 24 | "./e2e/tsconfig.e2e.json" 25 | ], 26 | "sourceType": "module", 27 | "ecmaFeatures": { 28 | "modules": true 29 | } 30 | }, 31 | "plugins": ["@typescript-eslint", "@angular-eslint/eslint-plugin"], 32 | "rules": { 33 | "@typescript-eslint/indent": [ 34 | "error", 35 | 2, 36 | { 37 | "SwitchCase": 1, 38 | "CallExpression": { 39 | "arguments": "first" 40 | }, 41 | "FunctionExpression": { 42 | "parameters": "first" 43 | }, 44 | "FunctionDeclaration": { 45 | "parameters": "first" 46 | } 47 | } 48 | ], 49 | "@typescript-eslint/no-empty-function": 0, 50 | "@typescript-eslint/no-explicit-any": 0, 51 | "@typescript-eslint/no-var-requires": 0, 52 | "@typescript-eslint/no-unsafe-call": 0, 53 | "@typescript-eslint/no-unsafe-member-access": 0, 54 | "@typescript-eslint/no-unsafe-assignment": 0, 55 | "@typescript-eslint/no-unsafe-return": 0, 56 | "@typescript-eslint/no-floating-promises": 0, 57 | "@typescript-eslint/explicit-function-return-type": 0, 58 | "@typescript-eslint/semi": "error", 59 | "@angular-eslint/use-injectable-provided-in": "error", 60 | "@angular-eslint/no-attribute-decorator": "error", 61 | "@typescript-eslint/explicit-module-boundary-types": "off" 62 | } 63 | }, 64 | { 65 | "files": ["*.component.html"], 66 | "parser": "@angular-eslint/template-parser", 67 | "plugins": ["@angular-eslint/template"], 68 | "rules": { 69 | "@angular-eslint/template/banana-in-box": "error", 70 | "@angular-eslint/template/no-negated-async": "error" 71 | } 72 | } 73 | ] 74 | } 75 | -------------------------------------------------------------------------------- /electron/.github/workflows/clean-artifacts.yml: -------------------------------------------------------------------------------- 1 | name: clean artifacts 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | clean: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: cleanup 13 | uses: glassechidna/artifact-cleaner@master 14 | with: 15 | minimumAge: 86400 16 | -------------------------------------------------------------------------------- /electron/.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: 'Windows Build' 2 | 3 | on: 4 | create: 5 | tags: 6 | - '*' 7 | 8 | workflow_dispatch: 9 | 10 | jobs: 11 | build: 12 | runs-on: 'windows-latest' 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Use Node.js 14.x 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: 14 20 | 21 | - name: Install Dependencies 22 | run: npm install --no-optional 23 | - uses: olegtarasov/get-tag@v2.1 24 | id: tagName 25 | - name: Set Version Number 26 | run: | 27 | npx replace-in-files-cli --string="##version##" --replacement="${{ steps.tagName.outputs.tag }}" "src/**/*" "scripts/**/*" 28 | - run: node "./scripts/version.script.js" 29 | - name: Build the app 30 | run: npm run electron:windows 31 | - run: node "./scripts/copy-file.js" 32 | - uses: 'marvinpinto/action-automatic-releases@latest' 33 | with: 34 | repo_token: '${{ secrets.GITHUB_TOKEN }}' 35 | automatic_release_tag: 'latest' 36 | prerelease: false 37 | files: | 38 | release/*.exe 39 | -------------------------------------------------------------------------------- /electron/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | ./dist 5 | /dist 6 | /tmp 7 | /out-tsc 8 | /app-builds 9 | /release 10 | main.js 11 | src/**/*.js 12 | !src/karma.conf.js 13 | *.js.map 14 | 15 | # dependencies 16 | /node_modules 17 | 18 | # IDEs and editors 19 | /.idea 20 | .project 21 | .classpath 22 | .c9/ 23 | *.launch 24 | .settings/ 25 | *.sublime-workspace 26 | 27 | # IDE - VSCode 28 | .vscode/* 29 | .vscode/settings.json 30 | !.vscode/tasks.json 31 | !.vscode/launch.json 32 | !.vscode/extensions.json 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | testem.log 41 | /typings 42 | 43 | # e2e 44 | /e2e/*.js 45 | !/e2e/protractor.conf.js 46 | /e2e/*.map 47 | 48 | # System Files 49 | .DS_Store 50 | Thumbs.db 51 | -------------------------------------------------------------------------------- /electron/.npmrc: -------------------------------------------------------------------------------- 1 | save=true 2 | save-exact=true 3 | -------------------------------------------------------------------------------- /electron/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Electron Main Renderer", 9 | "type": "node", 10 | "request": "launch", 11 | "protocol": "inspector", 12 | // Prelaunch task compiles main.ts for Electron & starts Angular dev server. 13 | "preLaunchTask": "Build.All", 14 | "cwd": "${workspaceFolder}", 15 | "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron", 16 | "runtimeArgs": [ 17 | "--serve", 18 | ".", 19 | "--remote-debugging-port=9222" 20 | ], 21 | "windows": { 22 | "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd" 23 | } 24 | }, { 25 | "name": "Karma Attach Chrome", 26 | "type": "chrome", 27 | "request": "attach", 28 | "port": 9222, 29 | "webRoot": "${workspaceFolder}/", 30 | "sourceMaps": true, 31 | "timeout": 30000, 32 | "trace": true 33 | } 34 | 35 | ] 36 | } -------------------------------------------------------------------------------- /electron/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Build.All", 6 | "type": "shell", 7 | "command": "npm run electron:serve-tsc && ng serve", 8 | "isBackground": true, 9 | "group": { 10 | "kind": "build", 11 | "isDefault": true 12 | }, 13 | "problemMatcher": { 14 | "owner": "typescript", 15 | "source": "ts", 16 | "applyTo": "closedDocuments", 17 | "fileLocation": ["relative", "${cwd}"], 18 | "pattern": "$tsc", 19 | "background": { 20 | "activeOnStart": true, 21 | "beginsPattern": "^.*", 22 | "endsPattern": "^.*Compiled successfully.*" 23 | } 24 | } 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /electron/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /electron/README.md: -------------------------------------------------------------------------------- 1 | # GUI for Windows Package Manager 2 | 3 | - https://github.com/microsoft/winget-cli 4 | 5 | ![img1](https://i.imgur.com/Dse0nIB.png) 6 | 7 | ## Contributing 8 | 9 | Feel free to Contribute 10 | 11 | ## Flutter 12 | 13 | Plan to do a Flutter Version of this Project to save .exe File Size 14 | -------------------------------------------------------------------------------- /electron/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /electron/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "angular-electron": { 7 | "root": "", 8 | "sourceRoot": "src", 9 | "projectType": "application", 10 | "architect": { 11 | "build": { 12 | "builder": "@angular-builders/custom-webpack:browser", 13 | "options": { 14 | "outputPath": "dist", 15 | "index": "src/index.html", 16 | "main": "src/main.ts", 17 | "tsConfig": "src/tsconfig.app.json", 18 | "polyfills": "src/polyfills.ts", 19 | "assets": [ 20 | { 21 | "glob": "**/*", 22 | "input": "src/assets", 23 | "output": "assets" 24 | }, 25 | { 26 | "glob": "**/*.svg", 27 | "input": "node_modules/ionicons/dist/ionicons/svg", 28 | "output": "./svg" 29 | } 30 | ], 31 | "styles": ["src/styles.scss"], 32 | "scripts": [], 33 | "customWebpackConfig": { 34 | "path": "./angular.webpack.js" 35 | } 36 | }, 37 | "configurations": { 38 | "dev": { 39 | "optimization": false, 40 | "outputHashing": "all", 41 | "sourceMap": true, 42 | "namedChunks": false, 43 | "aot": false, 44 | "extractLicenses": true, 45 | "vendorChunk": false, 46 | "buildOptimizer": false, 47 | "fileReplacements": [ 48 | { 49 | "replace": "src/environments/environment.ts", 50 | "with": "src/environments/environment.dev.ts" 51 | } 52 | ] 53 | }, 54 | "web": { 55 | "optimization": false, 56 | "outputHashing": "all", 57 | "sourceMap": true, 58 | "namedChunks": false, 59 | "aot": false, 60 | "extractLicenses": true, 61 | "vendorChunk": false, 62 | "buildOptimizer": false, 63 | "fileReplacements": [ 64 | { 65 | "replace": "src/environments/environment.ts", 66 | "with": "src/environments/environment.web.ts" 67 | } 68 | ] 69 | }, 70 | "production": { 71 | "optimization": true, 72 | "outputHashing": "all", 73 | "sourceMap": false, 74 | "namedChunks": false, 75 | "aot": true, 76 | "extractLicenses": true, 77 | "vendorChunk": false, 78 | "buildOptimizer": true, 79 | "fileReplacements": [ 80 | { 81 | "replace": "src/environments/environment.ts", 82 | "with": "src/environments/environment.prod.ts" 83 | } 84 | ] 85 | } 86 | } 87 | }, 88 | "serve": { 89 | "builder": "@angular-builders/custom-webpack:dev-server", 90 | "options": { 91 | "browserTarget": "angular-electron:build" 92 | }, 93 | "configurations": { 94 | "dev": { 95 | "browserTarget": "angular-electron:build:dev" 96 | }, 97 | "web": { 98 | "browserTarget": "angular-electron:build:web" 99 | }, 100 | "production": { 101 | "browserTarget": "angular-electron:build:production" 102 | } 103 | } 104 | }, 105 | "extract-i18n": { 106 | "builder": "@angular-devkit/build-angular:extract-i18n", 107 | "options": { 108 | "browserTarget": "angular-electron:build" 109 | } 110 | }, 111 | "test": { 112 | "builder": "@angular-builders/custom-webpack:karma", 113 | "options": { 114 | "main": "src/test.ts", 115 | "polyfills": "src/polyfills-test.ts", 116 | "tsConfig": "src/tsconfig.spec.json", 117 | "karmaConfig": "src/karma.conf.js", 118 | "scripts": [], 119 | "styles": ["src/styles.scss"], 120 | "assets": ["src/assets"], 121 | "customWebpackConfig": { 122 | "path": "./angular.webpack.js" 123 | } 124 | } 125 | }, 126 | "lint": { 127 | "builder": "@angular-eslint/builder:lint", 128 | "options": { 129 | "eslintConfig": ".eslintrc.json", 130 | "lintFilePatterns": ["src/**.ts", "main.ts"] 131 | } 132 | } 133 | } 134 | }, 135 | "angular-electron-e2e": { 136 | "root": "e2e", 137 | "projectType": "application", 138 | "architect": { 139 | "lint": { 140 | "builder": "@angular-eslint/builder:lint", 141 | "options": { 142 | "eslintConfig": ".eslintrc.json", 143 | "lintFilePatterns": ["e2e/**.ts"] 144 | } 145 | } 146 | } 147 | } 148 | }, 149 | "defaultProject": "angular-electron", 150 | "cli": { 151 | "defaultCollection": "@ionic/angular-toolkit" 152 | }, 153 | "schematics": { 154 | "@ionic/angular-toolkit:component": { 155 | "styleext": "scss" 156 | }, 157 | "@ionic/angular-toolkit:page": { 158 | "styleext": "scss" 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /electron/angular.webpack.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom angular webpack configuration 3 | */ 4 | 5 | module.exports = (config, options) => { 6 | config.target = 'electron-renderer'; 7 | 8 | if (options.fileReplacements) { 9 | for (let fileReplacement of options.fileReplacements) { 10 | if (fileReplacement.replace !== 'src/environments/environment.ts') { 11 | continue; 12 | } 13 | 14 | let fileReplacementParts = fileReplacement['with'].split('.'); 15 | if ( 16 | fileReplacementParts.length > 1 && 17 | ['web'].indexOf(fileReplacementParts[1]) >= 0 18 | ) { 19 | config.target = 'web'; 20 | } 21 | break; 22 | } 23 | } 24 | 25 | return config; 26 | }; 27 | -------------------------------------------------------------------------------- /electron/data/icon-no-bg-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/data/icon-no-bg-small.png -------------------------------------------------------------------------------- /electron/data/icon-no-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/data/icon-no-bg.png -------------------------------------------------------------------------------- /electron/data/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/data/icon.png -------------------------------------------------------------------------------- /electron/e2e/common-setup.ts: -------------------------------------------------------------------------------- 1 | const Application = require('spectron').Application; 2 | const electronPath = require('electron'); // Require Electron from the binaries included in node_modules. 3 | const path = require('path'); 4 | 5 | export default function setup(): void { 6 | beforeEach(async function () { 7 | this.app = new Application({ 8 | // Your electron path can be any binary 9 | // i.e for OSX an example path could be '/Applications/MyApp.app/Contents/MacOS/MyApp' 10 | // But for the sake of the example we fetch it from our node_modules. 11 | path: electronPath, 12 | 13 | // Assuming you have the following directory structure 14 | 15 | // |__ my project 16 | // |__ ... 17 | // |__ main.js 18 | // |__ package.json 19 | // |__ index.html 20 | // |__ ... 21 | // |__ test 22 | // |__ spec.js <- You are here! ~ Well you should be. 23 | 24 | // The following line tells spectron to look and use the main.js file 25 | // and the package.json located 1 level above. 26 | args: [path.join(__dirname, '..')], 27 | webdriverOptions: {} 28 | }); 29 | 30 | await this.app.start(); 31 | }); 32 | 33 | afterEach(async function () { 34 | if (this.app && this.app.isRunning()) { 35 | await this.app.stop(); 36 | } 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /electron/e2e/main.e2e.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { SpectronClient } from 'spectron'; 3 | 4 | import commonSetup from './common-setup'; 5 | 6 | describe('angular-electron App', function () { 7 | 8 | commonSetup.apply(this); 9 | 10 | let client: SpectronClient; 11 | 12 | beforeEach(function() { 13 | client = this.app.client; 14 | }); 15 | 16 | it('creates initial windows', async function () { 17 | const count = await client.getWindowCount(); 18 | expect(count).to.equal(1); 19 | }); 20 | 21 | it('should display message saying App works !', async function () { 22 | const elem = await client.$('app-home h1'); 23 | const text = await elem.getText(); 24 | expect(text).to.equal('App works !'); 25 | }); 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /electron/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "types": [ 7 | "mocha", 8 | "node" 9 | ] 10 | }, 11 | "include": [ 12 | "**.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /electron/electron-builder.json: -------------------------------------------------------------------------------- 1 | { 2 | "productName": "Windows Package Manager GUI", 3 | "appId": "de.codext.winget-gui", 4 | "directories": { 5 | "output": "release/" 6 | }, 7 | "publish": [ 8 | { 9 | "provider": "generic", 10 | "url": "https://ftp.codext.de/winget-gui/released/" 11 | } 12 | ], 13 | "files": [ 14 | "**/*", 15 | "!**/*.ts", 16 | "!stuff/", 17 | "!socketio-node/", 18 | "!old/", 19 | "!.github", 20 | "!.vscode", 21 | "!.code-workspace", 22 | "!.npmrc", 23 | "!*.md", 24 | "!package.json", 25 | "!package-lock.json", 26 | "!src/", 27 | "!e2e/", 28 | "!hooks/", 29 | "!_config.yml", 30 | "!angular.json", 31 | "!tsconfig*.json", 32 | "!tslint.json", 33 | "!.eslintrc.json", 34 | "!karma.conf.js", 35 | "!angular.webpack.js", 36 | "!*.map" 37 | ], 38 | "win": { 39 | "icon": "dist/assets/icons", 40 | "target": ["portable"] 41 | }, 42 | "nsis": { 43 | "allowElevation": true, 44 | "deleteAppDataOnUninstall": true, 45 | "oneClick": true, 46 | "perMachine": true, 47 | "allowToChangeInstallationDirectory": false, 48 | "runAfterFinish": true, 49 | "createStartMenuShortcut": true, 50 | "createDesktopShortcut": true 51 | }, 52 | "portable": {}, 53 | "mac": { 54 | "icon": "dist/assets/icons", 55 | "target": ["dmg"] 56 | }, 57 | "linux": { 58 | "icon": "dist/assets/icons", 59 | "target": ["AppImage"] 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /electron/ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "winget-gui", 3 | "integrations": {}, 4 | "type": "angular" 5 | } 6 | -------------------------------------------------------------------------------- /electron/main.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | /* eslint-disable @typescript-eslint/restrict-plus-operands */ 3 | require('@electron/remote/main').initialize(); 4 | 5 | import { app, BrowserWindow, dialog, Menu, nativeImage, Tray } from 'electron'; 6 | import { autoUpdater } from 'electron-updater'; 7 | 8 | import * as path from 'path'; 9 | import * as url from 'url'; 10 | 11 | let type: string; 12 | if (process.platform === 'win32') { 13 | type = 'win'; 14 | } 15 | if (process.platform === 'darwin') { 16 | type = 'macos'; 17 | } 18 | if (process.platform === 'linux') { 19 | type = 'linux'; 20 | } 21 | 22 | autoUpdater.setFeedURL(`https://ftp.codext.de/winget-gui/${type}/`); 23 | autoUpdater.autoDownload = true; 24 | 25 | autoUpdater.on('download-progress', (progressObj) => { 26 | let log_message = 'Download speed: ' + progressObj.bytesPerSecond; 27 | log_message = log_message + ' - Downloaded ' + progressObj.percent + '%'; 28 | log_message = 29 | log_message + 30 | ' (' + 31 | progressObj.transferred + 32 | '/' + 33 | progressObj.total + 34 | ')'; 35 | }); 36 | autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => { 37 | const dialogOpts = { 38 | type: 'info', 39 | buttons: ['Neustart', 'Später'], 40 | title: 'Anwendungsaktualisierung', 41 | message: process.platform === 'win32' ? releaseNotes : releaseName, 42 | detail: 43 | 'Eine neue Version wurde heruntergeladen. Starten Sie die Anwendung neu, um die Updates anzuwenden.', 44 | }; 45 | 46 | dialog.showMessageBox(dialogOpts).then((returnValue) => { 47 | if (returnValue.response === 0) autoUpdater.quitAndInstall(); 48 | }); 49 | }); 50 | 51 | let hidden, tray, serve; 52 | 53 | let win: BrowserWindow = null; 54 | const gotTheLock = app.requestSingleInstanceLock(); 55 | 56 | const args = process.argv.slice(1); 57 | serve = args.some((val) => val === '--serve'); 58 | hidden = args.some((val) => val === '--hidden'); 59 | 60 | // eslint-disable-next-line @typescript-eslint/require-await 61 | async function createWindow(): Promise { 62 | autoUpdater.checkForUpdates(); 63 | app.setAppUserModelId('de.codext.remotedesktop-control'); 64 | app.allowRendererProcessReuse = false; 65 | 66 | // Create the browser window. 67 | win = new BrowserWindow({ 68 | width: 410, 69 | minWidth: 250, 70 | minHeight: 250, 71 | height: 600, 72 | icon: path.join(__dirname, 'data/icon.png'), 73 | show: !hidden, 74 | titleBarStyle: process.platform === 'darwin' ? 'hidden' : 'default', 75 | frame: process.platform === 'darwin' ? true : false, 76 | center: true, 77 | backgroundColor: '#252a33', 78 | webPreferences: { 79 | nodeIntegration: true, 80 | allowRunningInsecureContent: serve ? true : false, 81 | contextIsolation: false, 82 | enableRemoteModule: true, 83 | }, 84 | }); 85 | const iconPath = path.join(__dirname, 'data/icon-no-bg-small.png'); 86 | 87 | tray = new Tray(nativeImage.createFromPath(iconPath)); 88 | const contextMenu = Menu.buildFromTemplate([ 89 | { 90 | label: 'Öffnen', 91 | click: () => { 92 | win?.show(); 93 | }, 94 | }, 95 | { 96 | label: 'Schließen', 97 | click: () => { 98 | win?.close(); 99 | app?.quit(); 100 | }, 101 | }, 102 | ]); 103 | tray.setToolTip('Windows Package Manager GUI'); 104 | tray.setContextMenu(contextMenu); 105 | 106 | tray.on('click', () => { 107 | win.show(); 108 | }); 109 | 110 | if (serve) { 111 | win.webContents.openDevTools(); 112 | require('electron-reload')(__dirname, { 113 | electron: require(`${__dirname}/node_modules/electron`), 114 | }); 115 | win.loadURL('http://localhost:4200/#/home'); 116 | } else { 117 | win.loadURL( 118 | url.format({ 119 | pathname: path.join(__dirname, 'dist/index.html'), 120 | protocol: 'file:', 121 | slashes: true, 122 | }) 123 | ); 124 | } 125 | 126 | // win.webContents.openDevTools(); 127 | 128 | // Emitted when the window is closed. 129 | win.on('closed', () => { 130 | // Dereference the window object, usually you would store window 131 | // in an array if your app supports multi windows, this is the time 132 | // when you should delete the corresponding element. 133 | win = null; 134 | }); 135 | 136 | /*win.on('close', (e) => { 137 | e.preventDefault(); 138 | win.destroy(); 139 | });*/ 140 | 141 | return win; 142 | } 143 | 144 | try { 145 | // Quit when all windows are closed. 146 | app.on('window-all-closed', () => { 147 | // On OS X it is common for applications and their menu bar 148 | // to stay active until the user quits explicitly with Cmd + Q 149 | if (process.platform !== 'darwin') { 150 | app.quit(); 151 | } 152 | }); 153 | 154 | if (!gotTheLock) { 155 | app.quit(); 156 | } else { 157 | app.on('second-instance', (event, commandLine, workingDirectory) => { 158 | // Someone tried to run a second instance, we should focus our window. 159 | if (win) { 160 | win.show(); 161 | win.focus(); 162 | // win.restore(); 163 | // if (win.isMinimized()) win.restore(); 164 | } 165 | }); 166 | 167 | // Create myWindow, load the rest of the app, etc... 168 | // eslint-disable-next-line @typescript-eslint/no-misused-promises 169 | app.on('ready', async () => { 170 | await createWindow(); 171 | }); 172 | } 173 | 174 | app.on('activate', () => { 175 | // On OS X it's common to re-create a window in the app when the 176 | // dock icon is clicked and there are no other windows open. 177 | if (win === null) { 178 | createWindow(); 179 | } 180 | }); 181 | } catch (e) { 182 | console.log('e', e); 183 | // Catch Error 184 | // throw e; 185 | } 186 | -------------------------------------------------------------------------------- /electron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "winget-gui", 3 | "version": "1.0.0", 4 | "description": "", 5 | "homepage": "https://codext.de", 6 | "browser": { 7 | "fs": false, 8 | "path": false, 9 | "os": false, 10 | "child_process": false, 11 | "stream": false, 12 | "crypto": false, 13 | "bcrypt": false 14 | }, 15 | "author": { 16 | "name": "Codext GmbH", 17 | "email": "info@codext.de" 18 | }, 19 | "main": "main.js", 20 | "private": true, 21 | "scripts": { 22 | "postinstall": "electron-builder install-app-deps && node ./scripts/fix.script.js", 23 | "ng": "ng", 24 | "start": "npm-run-all -p electron:serve ng:serve", 25 | "build": "npm run electron:serve-tsc && ng build --base-href ./", 26 | "build:dev": "npm run build -- -c dev", 27 | "build:prod": "npm run electron:serve-tsc && cross-env NODE_ENV=production ng build --prod", 28 | "ng:serve": "ng serve -c web --host 0.0.0.0", 29 | "electron:serve-tsc": "tsc -p tsconfig.serve.json", 30 | "electron:serve": "wait-on tcp:4200 && npm run electron:serve-tsc && npx electron . --serve", 31 | "electron:local": "npm run build:prod && npx electron .", 32 | "electron:build": "npm run build:prod && electron-builder build --publish=always", 33 | "electron:mac": "npm run build:prod && electron-builder build --mac --publish=always", 34 | "electron:linux": "npm run build:prod && electron-builder build --linux --publish=always", 35 | "electron:windows": "npm run build:prod && electron-builder build --windows --publish=always", 36 | "test": "ng test --watch=false", 37 | "test:watch": "ng test", 38 | "e2e": "npm run build:prod && cross-env TS_NODE_PROJECT='e2e/tsconfig.e2e.json' mocha --timeout 300000 --require ts-node/register e2e/**/*.e2e.ts", 39 | "version": "conventional-changelog -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md", 40 | "lint": "ng lint" 41 | }, 42 | "dependencies": { 43 | "@angular-devkit/architect": "0.1200.2", 44 | "@angular/animations": "^12.0.2", 45 | "@angular/cdk": "12.0.2", 46 | "@angular/forms": "^11.0.0 || ^12.0.0-0", 47 | "@angular/material": "12.0.2", 48 | "@capacitor-community/electron": "1.4.2", 49 | "@capacitor/core": "3.0.0", 50 | "@electron/remote": "1.1.0", 51 | "@ionic/angular": "^5.6.8", 52 | "@ionic/core": "^5.6.8", 53 | "@ionic/storage": "^3.0.4", 54 | "@ngneat/until-destroy": "8.0.4", 55 | "@types/simple-peer": "9.6.3", 56 | "build-number-generator": "1.0.0", 57 | "electron-clipboard-extended": "1.1.1", 58 | "electron-settings": "4.0.2", 59 | "electron-updater": "4.3.9", 60 | "electron-util": "github:dertieran/electron-util", 61 | "ng2-search-filter": "0.5.1", 62 | "ngx-electron": "2.2.0", 63 | "ngx-lazy": "1.0.3", 64 | "node-powershell": "4.0.0", 65 | "os": "0.1.1", 66 | "path": "0.12.7", 67 | "replace-in-files-cli": "1.0.0", 68 | "sweetalert2": "11.0.16" 69 | }, 70 | "devDependencies": { 71 | "@angular-builders/custom-webpack": "12.0.0", 72 | "@angular-devkit/build-angular": "12.0.2", 73 | "@angular-eslint/builder": "12.1.0", 74 | "@angular-eslint/eslint-plugin": "12.1.0", 75 | "@angular-eslint/eslint-plugin-template": "12.1.0", 76 | "@angular-eslint/schematics": "12.1.0", 77 | "@angular-eslint/template-parser": "12.1.0", 78 | "@angular/cli": "12.0.2", 79 | "@angular/common": "12.0.2", 80 | "@angular/compiler": "12.0.2", 81 | "@angular/compiler-cli": "12.0.2", 82 | "@angular/core": "12.0.2", 83 | "@angular/forms": "12.0.2", 84 | "@angular/language-service": "12.0.2", 85 | "@angular/platform-browser": "12.0.2", 86 | "@angular/platform-browser-dynamic": "12.0.2", 87 | "@angular/router": "12.0.2", 88 | "@ionic/angular-toolkit": "^4.0.0", 89 | "@ngx-translate/core": "13.0.0", 90 | "@ngx-translate/http-loader": "6.0.0", 91 | "@tailwindcss/aspect-ratio": "latest", 92 | "@tailwindcss/forms": "latest", 93 | "@tailwindcss/line-clamp": "latest", 94 | "@tailwindcss/typography": "latest", 95 | "@types/jasmine": "3.7.6", 96 | "@types/jasminewd2": "2.0.9", 97 | "@types/mocha": "8.2.2", 98 | "@types/node": "15.6.1", 99 | "@typescript-eslint/eslint-plugin": "4.26.0", 100 | "@typescript-eslint/eslint-plugin-tslint": "4.26.0", 101 | "@typescript-eslint/parser": "4.26.0", 102 | "chai": "4.3.4", 103 | "chokidar": "3.5.1", 104 | "conventional-changelog-cli": "2.1.1", 105 | "core-js": "3.13.1", 106 | "cross-env": "7.0.3", 107 | "electron": "13.0.1", 108 | "electron-builder": "22.10.5", 109 | "electron-rebuild": "2.3.5", 110 | "electron-reload": "1.5.0", 111 | "eslint": "7.27.0", 112 | "eslint-plugin-import": "2.23.4", 113 | "eslint-plugin-jsdoc": "35.1.1", 114 | "eslint-plugin-prefer-arrow": "1.2.3", 115 | "jasmine-core": "3.7.1", 116 | "jasmine-spec-reporter": "7.0.0", 117 | "karma": "6.3.2", 118 | "karma-coverage-istanbul-reporter": "3.0.3", 119 | "karma-electron": "7.0.0", 120 | "karma-jasmine": "4.0.1", 121 | "karma-jasmine-html-reporter": "1.6.0", 122 | "mocha": "8.4.0", 123 | "ngx-tailwind": "2.2.1", 124 | "npm-run-all": "4.1.5", 125 | "rxjs": "6.5.3", 126 | "spectron": "15.0.0", 127 | "tailwindcss": "^2.1.2", 128 | "ts-node": "10.0.0", 129 | "tslib": "2.2.0", 130 | "typescript": "^4.2", 131 | "wait-on": "5.3.0", 132 | "webdriver-manager": "12.1.8", 133 | "zone.js": "0.11.4" 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /electron/scripts/copy-file-mac.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var dir = './released'; 3 | 4 | if (!fs.existsSync(dir)) { 5 | fs.mkdirSync(dir); 6 | } 7 | 8 | var files = fs.readdirSync('./release/').filter((fn) => fn.endsWith('.dmg')); 9 | if (files[0]) { 10 | fs.copyFile('./release/' + files[0], './released/' + files[0], (err) => { 11 | if (err) throw err; 12 | }); 13 | } 14 | fs.copyFile('./release/latest-mac.yml', './released/latest-mac.yml', (err) => { 15 | if (err) throw err; 16 | }); 17 | -------------------------------------------------------------------------------- /electron/scripts/copy-file.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var dir = './released'; 3 | 4 | if (!fs.existsSync(dir)) { 5 | fs.mkdirSync(dir); 6 | } 7 | 8 | var files = fs.readdirSync('./release/').filter((fn) => fn.endsWith('.exe')); 9 | if (files[0]) { 10 | fs.copyFile('./release/' + files[0], './released/' + files[0], (err) => { 11 | if (err) throw err; 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /electron/scripts/fix.script.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | const file = 3 | './node_modules/mac-screen-capture-permissions/node_modules/electron-util/index.d.ts'; 4 | /* 5 | fs.readFile(file, 'utf8', function (err, data) { 6 | if (err) { 7 | return console.log(err); 8 | } 9 | data = data.replace(/AllElectron, /g, ''); 10 | data = data.replace('AllElectron | ', ''); 11 | 12 | fs.writeFile(file, data, 'utf8', function (err) { 13 | if (err) return console.log(err); 14 | }); 15 | }); 16 | */ 17 | -------------------------------------------------------------------------------- /electron/scripts/version.script.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | const { generate, validate, parse, format } = require('build-number-generator'); 3 | 4 | var file = 'package.json'; 5 | fs.readFile(file, 'utf8', function (err, data) { 6 | if (err) { 7 | return console.log(err); 8 | } 9 | 10 | var tmp = JSON.parse(data); 11 | tmp.version = '##version##'; // generate('##version##'); 12 | 13 | fs.writeFile(file, JSON.stringify(tmp), 'utf8', function (err) { 14 | if (err) return console.log(err); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /electron/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { HomePageModule } from '../pages/home/home.module'; 4 | import { SettingsPageModule } from '../pages/settings/settings.module'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | redirectTo: 'home', 10 | pathMatch: 'full', 11 | }, 12 | { 13 | path: 'home', 14 | loadChildren: () => HomePageModule, 15 | }, 16 | 17 | { 18 | path: 'settings', 19 | loadChildren: () => SettingsPageModule, 20 | }, 21 | ]; 22 | 23 | @NgModule({ 24 | imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })], 25 | exports: [RouterModule], 26 | }) 27 | export class AppRoutingModule {} 28 | -------------------------------------------------------------------------------- /electron/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 | 7 | 10 | 11 | 14 |
15 |
16 | 17 | 18 | 25 | 26 | 27 | 31 | 38 | 39 | {{ p.title }} 40 | 41 | 42 | 43 | 44 | 45 |
46 | Version{{ version }} 47 |
48 |
49 |
50 | 51 |
52 |
53 | -------------------------------------------------------------------------------- /electron/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | ion-item, 2 | ion-list { 3 | --background: transparent; 4 | } 5 | ion-content, 6 | ion-footer { 7 | --background: #252a33; 8 | 9 | ion-icon { 10 | color: #687384; 11 | } 12 | } 13 | 14 | ion-menu.main-menu { 15 | ion-content { 16 | --background: #252a33; 17 | 18 | ion-icon { 19 | color: #687384; 20 | } 21 | } 22 | 23 | ion-footer { 24 | ion-list { 25 | ion-item { 26 | --padding-top: 5px; 27 | --padding-bottom: 5px; 28 | } 29 | } 30 | } 31 | 32 | ion-list { 33 | margin-bottom: 0; 34 | background: transparent; 35 | border: none !important; 36 | 37 | ion-item { 38 | cursor: pointer; 39 | --padding-top: 10px; 40 | --padding-bottom: 10px; 41 | --background: transparent; 42 | position: relative; 43 | --inner-border-width: 0px 0px 0 0px; 44 | 45 | &:hover { 46 | background: rgba(0, 0, 0, 0.1); 47 | color: #398bf7; 48 | 49 | ion-icon, 50 | ion-label { 51 | color: #398bf7; 52 | } 53 | } 54 | 55 | &.active { 56 | position: relative; 57 | 58 | ion-label { 59 | h2 { 60 | font-weight: 600; 61 | } 62 | } 63 | 64 | ion-icon { 65 | color: #398bf7; 66 | } 67 | 68 | color: #398bf7; 69 | font-weight: 600; 70 | 71 | p { 72 | font-weight: 400; 73 | } 74 | 75 | &:after { 76 | position: absolute; 77 | left: 0; 78 | content: ''; 79 | width: 2px; 80 | background: #398bf7; 81 | height: 30px; 82 | top: 50%; 83 | transform: translateY(-50%); 84 | } 85 | } 86 | 87 | &.activated { 88 | background: rgba(0, 0, 0, 0.2); 89 | } 90 | 91 | ion-label { 92 | h2 { 93 | font-weight: 600; 94 | font-size: unset; 95 | text-align: left; 96 | } 97 | 98 | p { 99 | color: #656e82; 100 | } 101 | } 102 | 103 | color: #687384; 104 | } 105 | } 106 | } 107 | 108 | .version { 109 | text-align: center; 110 | padding: 10px 0; 111 | font-size: 16px; 112 | color: var(--ion-color-primary); 113 | font-weight: bold; 114 | small { 115 | opacity: 0.6; 116 | } 117 | } 118 | 119 | .split-pane-side { 120 | --border: none; 121 | } 122 | 123 | .action-bar { 124 | display: flex; 125 | align-items: center; 126 | justify-content: flex-end; 127 | padding-right: 10px; 128 | height: 30px; 129 | width: 100%; 130 | background: var(--ion-color-primary); 131 | -ms-overflow-style: scrollbar; 132 | -webkit-app-region: drag; 133 | 134 | .app-actions { 135 | display: flex; 136 | align-items: center; 137 | justify-content: center; 138 | -webkit-app-region: no-drag; 139 | 140 | button { 141 | &.close { 142 | &:hover { 143 | background: #f04747; 144 | } 145 | 146 | &:active { 147 | background: rgba(255, 0, 0, 0.5); 148 | } 149 | } 150 | 151 | display: flex; 152 | align-items: center; 153 | justify-content: center; 154 | background: transparent; 155 | color: #fff; 156 | padding: 0 8px; 157 | height: 20px; 158 | border-radius: 3px; 159 | transition: all 150ms ease-in-out; 160 | 161 | &:hover { 162 | background: rgba(0, 0, 0, 0.1); 163 | } 164 | 165 | &:active { 166 | background: rgba(0, 0, 0, 0.3); 167 | } 168 | 169 | &:focus { 170 | border: none; 171 | outline: none; 172 | } 173 | } 174 | } 175 | } 176 | 177 | .split-pane { 178 | top: 30px; // for header 179 | } 180 | 181 | ion-footer { 182 | ion-list { 183 | ion-item { 184 | --padding-top: 5px; 185 | --padding-bottom: 5px; 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /electron/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, waitForAsync } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | import { TranslateModule } from '@ngx-translate/core'; 5 | import { ElectronService } from './core/services'; 6 | 7 | describe('AppComponent', () => { 8 | beforeEach(waitForAsync(() => { 9 | TestBed.configureTestingModule({ 10 | declarations: [AppComponent], 11 | providers: [ElectronService], 12 | imports: [RouterTestingModule, TranslateModule.forRoot()] 13 | }).compileComponents(); 14 | })); 15 | 16 | it('should create the app', waitForAsync(() => { 17 | const fixture = TestBed.createComponent(AppComponent); 18 | const app = fixture.debugElement.componentInstance; 19 | expect(app).toBeTruthy(); 20 | })); 21 | }); 22 | -------------------------------------------------------------------------------- /electron/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { AfterViewInit, Component } from '@angular/core'; 2 | import { MatDialog } from '@angular/material/dialog'; 3 | import { ModalController } from '@ionic/angular'; 4 | import { ElectronService as NgxService } from 'ngx-electron'; 5 | import { AppConfig } from '../environments/environment'; 6 | import { AppService } from './core/services/app.service'; 7 | import { ElectronService } from './core/services/electron.service'; 8 | import { SettingsService } from './core/services/settings.service'; 9 | 10 | @Component({ 11 | selector: 'app-root', 12 | templateUrl: './app.component.html', 13 | styleUrls: ['./app.component.scss'], 14 | }) 15 | export class AppComponent implements AfterViewInit { 16 | platform = window.process; 17 | process = window.process; 18 | version = '##version##'; 19 | 20 | appPages = [ 21 | { title: 'Home', url: '/home', icon: 'code-working-outline' }, 22 | { title: 'Einstellungen', url: '/settings', icon: 'cog-outline' }, 23 | ]; 24 | 25 | constructor( 26 | public electronService: ElectronService, 27 | public appService: AppService, 28 | private settingsService: SettingsService, 29 | private ngxService: NgxService 30 | ) { 31 | console.log('AppConfig', AppConfig); 32 | } 33 | 34 | async ngAfterViewInit() { 35 | if (this.ngxService.isElectronApp) { 36 | await this.settingsService.load(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /electron/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { HashLocationStrategy, LocationStrategy } from '@angular/common'; 2 | import { HttpClient, HttpClientModule } from '@angular/common/http'; 3 | import { NgModule } from '@angular/core'; 4 | import { FormsModule } from '@angular/forms'; 5 | import { MatDialogModule } from '@angular/material/dialog'; 6 | import { MatTooltipModule } from '@angular/material/tooltip'; 7 | import { BrowserModule } from '@angular/platform-browser'; 8 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 9 | import { RouteReuseStrategy } from '@angular/router'; 10 | import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; 11 | // NG Translate 12 | import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; 13 | import { TranslateHttpLoader } from '@ngx-translate/http-loader'; 14 | import { NgxElectronModule } from 'ngx-electron'; 15 | import { AppRoutingModule } from './app-routing.module'; 16 | import { AppComponent } from './app.component'; 17 | import { CoreModule } from './core/core.module'; 18 | 19 | export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader { 20 | return new TranslateHttpLoader(http, './assets/i18n/', '.json'); 21 | } 22 | 23 | @NgModule({ 24 | declarations: [AppComponent], 25 | imports: [ 26 | BrowserModule, 27 | BrowserAnimationsModule, 28 | FormsModule, 29 | HttpClientModule, 30 | CoreModule, 31 | AppRoutingModule, 32 | TranslateModule.forRoot({ 33 | loader: { 34 | provide: TranslateLoader, 35 | useFactory: HttpLoaderFactory, 36 | deps: [HttpClient], 37 | }, 38 | }), 39 | IonicModule.forRoot(), 40 | NgxElectronModule, 41 | MatTooltipModule, 42 | MatDialogModule, 43 | ], 44 | providers: [ 45 | { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, 46 | { provide: LocationStrategy, useClass: HashLocationStrategy }, 47 | ], 48 | bootstrap: [AppComponent], 49 | }) 50 | export class AppModule {} 51 | -------------------------------------------------------------------------------- /electron/src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | @NgModule({ 5 | declarations: [], 6 | imports: [ 7 | CommonModule 8 | ] 9 | }) 10 | export class CoreModule { } 11 | -------------------------------------------------------------------------------- /electron/src/app/core/services/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root', 5 | }) 6 | export class AppService { 7 | sideMenu = true; 8 | actionBar = true; 9 | } 10 | -------------------------------------------------------------------------------- /electron/src/app/core/services/command.service.ts: -------------------------------------------------------------------------------- 1 | import { ElectronService } from './electron.service'; 2 | import { Injectable } from '@angular/core'; 3 | import * as path from 'path'; 4 | import * as os from 'os'; 5 | import { ElectronService as NgxService } from 'ngx-electron'; 6 | 7 | @Injectable({ providedIn: 'root' }) 8 | export class CommandService { 9 | constructor( 10 | private electron: ElectronService, 11 | private ngxService: NgxService 12 | ) {} 13 | 14 | powershell(script) { 15 | return new Promise((resolve, reject) => { 16 | const ps = new this.electron.powershell({ 17 | executionPolicy: 'Bypass', 18 | noProfile: true, 19 | }); 20 | 21 | ps.addCommand(script); 22 | ps.invoke() 23 | .then((output) => { 24 | console.log(output); 25 | resolve(output); 26 | }) 27 | .catch((err) => { 28 | console.log(err); 29 | reject(err); 30 | }); 31 | }); 32 | } 33 | 34 | batch(script) { 35 | return new Promise((resolve, reject) => { 36 | const spawn = this.electron.childProcess.spawn; 37 | const fs = this.electron.fs; 38 | console.log('os', os); 39 | const scriptDir = path.join(os.tmpdir(), 'windows10-tweak-script.bat'); 40 | 41 | try { 42 | fs.writeFileSync(scriptDir, script, 'utf-8'); 43 | 44 | const ps = new this.electron.powershell({ 45 | executionPolicy: 'Bypass', 46 | noProfile: true, 47 | }); 48 | 49 | ps.addCommand( 50 | `Start-Process cmd -ArgumentList '/c ${scriptDir}' -Verb runas -Wait` 51 | ); 52 | ps.invoke() 53 | .then((output) => { 54 | console.log(output); 55 | resolve(output); 56 | }) 57 | .catch((err) => { 58 | console.log(err); 59 | reject(err); 60 | }); 61 | } catch (e) { 62 | reject(e); 63 | } 64 | }); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /electron/src/app/core/services/electron.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import * as childProcess from 'child_process'; 3 | import { 4 | app, 5 | BrowserWindow, 6 | desktopCapturer, 7 | ipcRenderer, 8 | remote, 9 | screen, 10 | webFrame, 11 | } from 'electron'; 12 | import * as settings from 'electron-settings'; 13 | import * as autoUpdater from 'electron-updater'; 14 | import * as fs from 'fs'; 15 | import * as powershell from 'node-powershell'; 16 | import * as os from 'os'; 17 | import * as path from 'path'; 18 | 19 | @Injectable({ 20 | providedIn: 'root', 21 | }) 22 | export class ElectronService { 23 | app: typeof app; 24 | ipcRenderer: typeof ipcRenderer; 25 | desktopCapturer: typeof desktopCapturer; 26 | webFrame: typeof webFrame; 27 | remote: typeof remote; 28 | childProcess: typeof childProcess; 29 | fs: typeof fs; 30 | os: typeof os; 31 | path: typeof path; 32 | window: BrowserWindow; 33 | settings: typeof settings; 34 | autoUpdater: typeof autoUpdater; 35 | screen: typeof screen; 36 | powershell: typeof powershell; 37 | 38 | get isElectron(): boolean { 39 | return !!(window && window.process && window.process.type); 40 | } 41 | 42 | constructor() { 43 | // Conditional imports 44 | if (this.isElectron) { 45 | this.ipcRenderer = window.require('electron').ipcRenderer; 46 | this.autoUpdater = window.require('electron-updater'); 47 | this.webFrame = window.require('electron').webFrame; 48 | this.screen = window.require('electron').screen; 49 | this.remote = window.require('electron').remote; 50 | this.app = this.remote.app; 51 | this.os = window.require('os'); 52 | // this.autoLaunch = window.require('auto-launch'); 53 | this.window = window.require('electron').remote.getCurrentWindow(); 54 | this.settings = window.require('electron-settings'); 55 | this.childProcess = window.require('child_process'); 56 | this.fs = window.require('fs'); 57 | this.path = window.require('path'); 58 | this.powershell = window.require('node-powershell'); 59 | 60 | this.remote.globalShortcut.register('Control+Shift+I', () => { 61 | return false; 62 | }); 63 | } 64 | } 65 | 66 | minimize() { 67 | this.window.minimize(); 68 | } 69 | 70 | maximize() { 71 | if (!this.window.isMaximized()) { 72 | this.window.maximize(); 73 | } else { 74 | this.window.unmaximize(); 75 | } 76 | } 77 | 78 | hide() { 79 | this.window.hide(); 80 | } 81 | 82 | close() { 83 | this.window.close(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /electron/src/app/core/services/settings.service.ts: -------------------------------------------------------------------------------- 1 | import { TranslateService } from '@ngx-translate/core'; 2 | import { ElectronService } from './electron.service'; 3 | import { Injectable } from '@angular/core'; 4 | 5 | @Injectable({ 6 | providedIn: 'root', 7 | }) 8 | export class SettingsService { 9 | settings = {}; 10 | 11 | language: { text: string; code: string } = { 12 | text: 'Deutsch', 13 | code: 'de', 14 | }; 15 | 16 | constructor( 17 | private electronService: ElectronService, 18 | private translate: TranslateService 19 | ) {} 20 | 21 | async load() { 22 | const settings: any = await this.electronService.settings.get('settings'); 23 | console.log(settings); 24 | if (settings?.language) { 25 | this.language = settings.language; 26 | this.translate.setDefaultLang(settings?.language.code); 27 | } else { 28 | this.translate.setDefaultLang('de'); 29 | } 30 | Object.assign(this.settings, settings); 31 | } 32 | 33 | async saveSettings(settings) { 34 | Object.assign(this.settings, settings); 35 | await this.electronService.settings.set('settings', this.settings); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /electron/src/app/core/services/storage.service.ts: -------------------------------------------------------------------------------- 1 | import { Plugins } from '@capacitor/core'; 2 | import { AppConfig } from '../../../environments/environment'; 3 | 4 | const { Storage } = Plugins; 5 | 6 | export async function set(key: string, value: any): Promise { 7 | await Storage.set({ 8 | key: `${AppConfig.appName}-${key}`, 9 | value: JSON.stringify(value), 10 | }); 11 | } 12 | 13 | export async function get(key: string): Promise { 14 | let item = await Storage.get({ key: `${AppConfig.appName}-${key}` }); 15 | try { 16 | item = JSON.parse(item.value); 17 | return item; 18 | } catch (error) { 19 | return item; 20 | } 21 | } 22 | 23 | export async function remove(key: string): Promise { 24 | await Storage.remove({ 25 | key: `${AppConfig.appName}-${key}`, 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /electron/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/.gitkeep -------------------------------------------------------------------------------- /electron/src/assets/animations/9953-loading-round.json: -------------------------------------------------------------------------------- 1 | {"v":"5.5.8","fr":29.9700012207031,"ip":0,"op":120.0000048877,"w":400,"h":400,"nm":"loading","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":-60,"s":[0,0]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[100,100]},{"t":60.0000024438501,"s":[0,0]}],"ix":3,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-60.0000024438501,"op":840.000034213901,"st":-60.0000024438501,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[0,0]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":60,"s":[100,100]},{"t":120.0000048877,"s":[0,0]}],"ix":3,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /electron/src/assets/animations/bell-green.json: -------------------------------------------------------------------------------- 1 | {"v":"5.6.6","fr":60,"ip":0,"op":91,"w":500,"h":500,"nm":"bell","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"bell Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[16.723,9.701],[3.059,5.272]],"o":[[-9.701,16.723],[-5.273,-3.059],[0,0]],"v":[[30.28,-11.208],[-17.565,1.507],[-30.28,-11.208]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.49411764705882355,0.8274509803921568,0.12941176470588237,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[250,73.762],"ix":2},"a":{"a":0,"k":[0,-345],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[20]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[-20]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[-10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":70,"s":[5]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":80,"s":[-5]},{"t":90,"s":[0]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,122.519],[57.999,0],[0,-58],[0,0],[0,0]],"o":[[0,-58],[-57.999,0],[0,122.519],[0,0],[0,0]],"v":[[105.017,-26.254],[0,-131.271],[-105.017,-26.254],[-157.525,131.271],[157.525,131.271]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.49411764705882355,0.8274509803921568,0.12941176470588237,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[249,75.271],"ix":2},"a":{"a":0,"k":[-1,-131],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[20]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[-19]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[-10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[5]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":70,"s":[-5]},{"t":80,"s":[0]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":180,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /electron/src/assets/animations/bell-white.json: -------------------------------------------------------------------------------- 1 | {"v":"5.6.6","fr":60,"ip":0,"op":91,"w":500,"h":500,"nm":"bell","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"bell Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[16.723,9.701],[3.059,5.272]],"o":[[-9.701,16.723],[-5.273,-3.059],[0,0]],"v":[[30.28,-11.208],[-17.565,1.507],[-30.28,-11.208]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.49411764705882355,0.8274509803921568,0.12941176470588237,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[250,73.762],"ix":2},"a":{"a":0,"k":[0,-345],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[20]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[-20]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[-10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":70,"s":[5]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":80,"s":[-5]},{"t":90,"s":[0]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,122.519],[57.999,0],[0,-58],[0,0],[0,0]],"o":[[0,-58],[-57.999,0],[0,122.519],[0,0],[0,0]],"v":[[105.017,-26.254],[0,-131.271],[-105.017,-26.254],[-157.525,131.271],[157.525,131.271]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.49411764705882355,0.8274509803921568,0.12941176470588237,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[249,75.271],"ix":2},"a":{"a":0,"k":[-1,-131],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[20]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[-19]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[-10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[5]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":70,"s":[-5]},{"t":80,"s":[0]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":180,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /electron/src/assets/animations/lf30_editor_PsHnfk.json: -------------------------------------------------------------------------------- 1 | {"v":"5.4.2","fr":29.9700012207031,"ip":0,"op":70.0000028511585,"w":540,"h":405,"nm":"Comp 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"core","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[270,202.5,0],"ix":2},"a":{"a":0,"k":[-30.082,-0.082,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":0,"s":[70,70,100],"e":[70,70,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":20,"s":[70,70,100],"e":[90,90,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":30,"s":[90,90,100],"e":[70,70,100]},{"t":70.0000028511585}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[200,200],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-30.082,-0.082],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":103.000004195276,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"small ripple","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p833_1_0p333_0"],"t":17,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":27,"s":[100],"e":[0]},{"t":60.0000024438501}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[270,202.5,0],"ix":2},"a":{"a":0,"k":[-30.082,-0.082,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":17,"s":[50,50,100],"e":[120,120,100]},{"t":60.0000024438501}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-30.082,-0.082],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":103.000004195276,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"large ripple","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":10,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":20,"s":[100],"e":[0]},{"t":50.0000020365418}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[270,202.5,0],"ix":2},"a":{"a":0,"k":[-30.082,-0.082,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":10,"s":[0,0,100],"e":[130,130,100]},{"t":40.0000016292334}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-30.082,-0.082],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":103.000004195276,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /electron/src/assets/animations/ring.json: -------------------------------------------------------------------------------- 1 | {"v":"5.6.10","fr":30,"ip":0,"op":84,"w":200,"h":200,"nm":"Bell02","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[100,100,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[-100,100,100]}},"ao":0,"ip":0,"op":2222,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 20","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-4.44},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":58,"s":[38.334,-29.113,0],"to":[0,0,0],"ti":[0,0,0]},{"t":68,"s":[59.574,-36.529,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":63,"s":[0]},{"t":69,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":63,"s":[100]},{"t":69,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":57,"op":69,"st":-32,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 19","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-4.44},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":50,"s":[38.334,-29.113,0],"to":[0,0,0],"ti":[0,0,0]},{"t":60,"s":[59.574,-36.529,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":55,"s":[0]},{"t":61,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":55,"s":[100]},{"t":61,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":49,"op":61,"st":-40,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 18","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-4.44},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":42,"s":[38.334,-29.113,0],"to":[0,0,0],"ti":[0,0,0]},{"t":52,"s":[59.574,-36.529,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":47,"s":[0]},{"t":53,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":47,"s":[100]},{"t":53,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":41,"op":53,"st":-48,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 17","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-4.44},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":34,"s":[38.334,-29.113,0],"to":[0,0,0],"ti":[0,0,0]},{"t":44,"s":[59.574,-36.529,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":39,"s":[0]},{"t":45,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":39,"s":[100]},{"t":45,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":33,"op":45,"st":-56,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Shape Layer 16","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-4.44},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":26,"s":[38.334,-29.113,0],"to":[0,0,0],"ti":[0,0,0]},{"t":36,"s":[59.574,-36.529,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":31,"s":[0]},{"t":37,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":31,"s":[100]},{"t":37,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":25,"op":37,"st":-64,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Shape Layer 15","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-4.44},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":18,"s":[38.334,-29.113,0],"to":[0,0,0],"ti":[0,0,0]},{"t":28,"s":[59.574,-36.529,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":23,"s":[0]},{"t":29,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":23,"s":[100]},{"t":29,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":17,"op":29,"st":-72,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Shape Layer 14","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-4.44},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[38.334,-29.113,0],"to":[0,0,0],"ti":[0,0,0]},{"t":20,"s":[59.574,-36.529,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":15,"s":[0]},{"t":21,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":15,"s":[100]},{"t":21,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":9,"op":21,"st":-80,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Shape Layer 13","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-4.44},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[38.334,-29.113,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[59.574,-36.529,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":7,"s":[0]},{"t":13,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":7,"s":[100]},{"t":13,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":1,"op":13,"st":-88,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Shape Layer 12","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":58,"s":[37.125,-26.188,0],"to":[0,0,0],"ti":[0,0,0]},{"t":68,"s":[58.875,-31.938,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":63,"s":[0]},{"t":69,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":63,"s":[100]},{"t":69,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":57,"op":69,"st":-32,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Shape Layer 11","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":50,"s":[37.125,-26.188,0],"to":[0,0,0],"ti":[0,0,0]},{"t":60,"s":[58.875,-31.938,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":55,"s":[0]},{"t":61,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":55,"s":[100]},{"t":61,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":49,"op":61,"st":-40,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Shape Layer 10","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":42,"s":[37.125,-26.188,0],"to":[0,0,0],"ti":[0,0,0]},{"t":52,"s":[58.875,-31.938,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":47,"s":[0]},{"t":53,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":47,"s":[100]},{"t":53,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":41,"op":53,"st":-48,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Shape Layer 9","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":34,"s":[37.125,-26.188,0],"to":[0,0,0],"ti":[0,0,0]},{"t":44,"s":[58.875,-31.938,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":39,"s":[0]},{"t":45,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":39,"s":[100]},{"t":45,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":33,"op":45,"st":-56,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Shape Layer 8","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":26,"s":[37.125,-26.188,0],"to":[0,0,0],"ti":[0,0,0]},{"t":36,"s":[58.875,-31.938,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":31,"s":[0]},{"t":37,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":31,"s":[100]},{"t":37,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":25,"op":37,"st":-64,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Shape Layer 7","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":18,"s":[37.125,-26.188,0],"to":[0,0,0],"ti":[0,0,0]},{"t":28,"s":[58.875,-31.938,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":23,"s":[0]},{"t":29,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":23,"s":[100]},{"t":29,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":17,"op":29,"st":-72,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Shape Layer 6","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[37.125,-26.188,0],"to":[0,0,0],"ti":[0,0,0]},{"t":20,"s":[58.875,-31.938,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":15,"s":[0]},{"t":21,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":15,"s":[100]},{"t":21,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":9,"op":21,"st":-80,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"Shape Layer 5","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[37.125,-26.188,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[58.875,-31.938,0]}]},"a":{"a":0,"k":[37.125,-26.188,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.782,-6.915],[0,-18.5]],"o":[[6.375,7.625],[0,9.763]],"v":[[30,-43.75],[44.25,-8.625]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":7,"s":[0]},{"t":13,"s":[50]}]},"e":{"a":1,"k":[{"i":{"x":[0.219],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[50]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.668],"y":[0]},"t":7,"s":[100]},{"t":13,"s":[50]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":1,"op":13,"st":-88,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"Shape Layer 4","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":3,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":13,"s":[-15.83,-0.158,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":23,"s":[15.636,-0.506,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":33,"s":[-15.83,-0.158,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":43,"s":[15.636,-0.506,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":53,"s":[-15.83,-0.158,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":63,"s":[15.636,-0.506,0],"to":[0,0,0],"ti":[0,0,0]},{"t":74,"s":[0,0,0]}]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-16.375],[0,16.75]],"o":[[0,16.625],[0,-16]],"v":[[-13,36],[12.5,36]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":0,"op":2222,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"Shape Layer 3","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-35.875],[0,-48.875]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":0,"op":2222,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"Shape Layer 1","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[-15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[-15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[-15]},{"i":{"x":[0.472],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[15]},{"t":71,"s":[0]}]},"p":{"a":0,"k":[0,-43.25,0]},"a":{"a":0,"k":[0,-43.25,0]},"s":{"a":0,"k":[-100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[15.5,0],[0,-29.25],[4,-4.25],[-7.5,0],[-4.5,0],[1.991,4.858],[0,19.75]],"o":[[-15.5,0],[0,15.375],[-4,4.25],[7.5,0],[4.5,0],[-3.125,-7.625],[0,-26.75]],"v":[[0.375,-35.5],[-27.375,1.25],[-37.5,28.5],[-35,35.75],[33.75,35.25],[40,30.875],[27.25,0.75]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":0,"op":2222,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /electron/src/assets/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/background.jpg -------------------------------------------------------------------------------- /electron/src/assets/i18n/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "Entire Screen": "Gesamter Bildschirm", 3 | "Screen 1": "Desktop 1", 4 | "Screen 2": "Desktop 2", 5 | "Screen 3": "Desktop 3", 6 | "Screen 4": "Desktop 4", 7 | "Screen 5": "Desktop 5", 8 | "Password": "Passwort", 9 | "Repeat Password": "Passwort wiederholen", 10 | "Cancel": "Abbrechen", 11 | "Save": "Speichern", 12 | "Password does not match": "Passwörter stimmen nicht überein", 13 | "Must contain at least 8 characters": "Muss mindestens 8 Zeichen enthalten", 14 | "Must contain at least one number": "Muss mindestens eine Zahl enthalten", 15 | "Must contain at least one capital letter": "Muss mindestens ein Großbuchstaben enthalten", 16 | "Must contain at least one lower case letter": "Muss mindestens ein Kleinbuchstaben enthalten", 17 | "Must contain at least one special character": "Muss mindestens ein Sonderzeichen enthalten", 18 | "Language": "Sprache", 19 | "Settings": "Einstellungen", 20 | "Add Password": "Passwort hinzufügen", 21 | "Unattended access": "Unbeaufsichtigten Zugriff", 22 | "Autostart": "Autostart", 23 | "Random ID": "Zufällige ID", 24 | "display name": "Anzeigename", 25 | "decline": "Ablehnen", 26 | "Accept": "Annehmen", 27 | "Connect": "Verbinden", 28 | "Change Password": "Passwort ändern", 29 | "Incoming Connection": "Neue Verbindung" 30 | } 31 | -------------------------------------------------------------------------------- /electron/src/assets/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "Entire Screen": "Entire Screen", 3 | "Screen 1": "Screen 1", 4 | "Screen 2": "Screen 2", 5 | "Screen 3": "Screen 3", 6 | "Screen 4": "Screen 4", 7 | "Screen 5": "Screen 5", 8 | "Password": "Password", 9 | "Repeat Password": "Repeat Password", 10 | "Cancel": "Cancel", 11 | "Save": "Save", 12 | "Password does not match": "Password does not match", 13 | "Must contain at least 8 characters": "Must contain at least 8 characters", 14 | "Must contain at least one number": "Must contain at least one number", 15 | "Must contain at least one capital letter": "Must contain at least one capital letter", 16 | "Must contain at least one lower case letter": "Must contain at least one lower case letter", 17 | "Must contain at least one special character": "Must contain at least one special character", 18 | "Language": "Language", 19 | "Settings": "Settings", 20 | "Add Password": "Add Password", 21 | "Unattended access": "Unattended access", 22 | "Autostart": "Autostart", 23 | "Random ID": "Random ID", 24 | "display name": "display name" 25 | } 26 | -------------------------------------------------------------------------------- /electron/src/assets/icons/DE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/icons/DE.png -------------------------------------------------------------------------------- /electron/src/assets/icons/US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/icons/US.png -------------------------------------------------------------------------------- /electron/src/assets/icons/favicon.256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/icons/favicon.256x256.png -------------------------------------------------------------------------------- /electron/src/assets/icons/favicon.512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/icons/favicon.512x512.png -------------------------------------------------------------------------------- /electron/src/assets/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/icons/favicon.ico -------------------------------------------------------------------------------- /electron/src/assets/icons/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/icons/favicon.png -------------------------------------------------------------------------------- /electron/src/assets/images/be.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/images/be.png -------------------------------------------------------------------------------- /electron/src/assets/images/screen-recording.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/electron/src/assets/images/screen-recording.png -------------------------------------------------------------------------------- /electron/src/environments/environment.dev.ts: -------------------------------------------------------------------------------- 1 | export const AppConfig = { 2 | production: false, 3 | environment: 'DEV', 4 | appName: 'winget-gui', 5 | }; 6 | -------------------------------------------------------------------------------- /electron/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const AppConfig = { 2 | production: true, 3 | environment: 'PROD', 4 | appName: 'winget-gui', 5 | }; 6 | -------------------------------------------------------------------------------- /electron/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | export const AppConfig = { 2 | production: false, 3 | environment: 'LOCAL', 4 | appName: 'winget-gui', 5 | }; 6 | -------------------------------------------------------------------------------- /electron/src/environments/environment.web.ts: -------------------------------------------------------------------------------- 1 | export const AppConfig = { 2 | production: false, 3 | environment: 'WEB', 4 | appName: 'winget-gui', 5 | }; 6 | -------------------------------------------------------------------------------- /electron/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WinGet GUI 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /electron/src/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-electron'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../coverage'), 20 | reports: [ 'html', 'lcovonly' ], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | browsers: ['AngularElectron'], 28 | customLaunchers: { 29 | AngularElectron: { 30 | base: 'Electron', 31 | flags: [ 32 | '--remote-debugging-port=9222' 33 | ], 34 | browserWindowOptions: { 35 | webPreferences: { 36 | nodeIntegration: true, 37 | nodeIntegrationInSubFrames: true, 38 | allowRunningInsecureContent: true, 39 | enableRemoteModule: true 40 | } 41 | } 42 | } 43 | } 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /electron/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { AppConfig } from './environments/environment'; 6 | 7 | if (AppConfig.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule, { 13 | preserveWhitespaces: false 14 | }) 15 | .catch(err => console.error(err)); 16 | -------------------------------------------------------------------------------- /electron/src/pages/home/home-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { HomePage } from './home.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: HomePage, 10 | }, 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule], 16 | }) 17 | export class HomePageRoutingModule {} 18 | -------------------------------------------------------------------------------- /electron/src/pages/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { MatButtonModule } from '@angular/material/button'; 5 | import { MatDialogModule } from '@angular/material/dialog'; 6 | import { MatTooltipModule } from '@angular/material/tooltip'; 7 | import { IonicModule } from '@ionic/angular'; 8 | import { TranslateModule } from '@ngx-translate/core'; 9 | import { HomePageRoutingModule } from './home-routing.module'; 10 | import { HomePage } from './home.page'; 11 | import { NumberDirective } from './number.directive'; 12 | 13 | import { Ng2SearchPipeModule } from 'ng2-search-filter'; 14 | import { LazyForDirective } from './lazyFor.directive'; 15 | import { ScrollingModule } from '@angular/cdk/scrolling'; 16 | 17 | @NgModule({ 18 | imports: [ 19 | CommonModule, 20 | FormsModule, 21 | IonicModule, 22 | HomePageRoutingModule, 23 | MatTooltipModule, 24 | MatDialogModule, 25 | MatButtonModule, 26 | TranslateModule, 27 | Ng2SearchPipeModule, 28 | ScrollingModule, 29 | ], 30 | declarations: [HomePage, NumberDirective, LazyForDirective], 31 | }) 32 | export class HomePageModule {} 33 | -------------------------------------------------------------------------------- /electron/src/pages/home/home.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 12 | 13 | Packages 14 | 15 | 16 | Installed 17 | 18 | 19 |
20 | 21 | 24 | 25 |
26 |
27 | 28 | 29 | 34 | 35 | 40 |
56 |
57 |

{{package[0]}}

58 |

59 | {{package[1]}} - {{package[2]}} 60 |

61 |
62 | 63 |
76 | Install 77 |
78 |
79 |
80 |
81 | 82 | 83 | 88 |
102 |
106 |

{{package[0]}}

107 |

108 | {{package[1]}} - {{package[2]}} 109 |

110 |
111 | 112 |
113 |
128 | Update 129 |
130 |
146 | Uninstall 147 |
148 |
149 |
150 |
151 |
152 |
153 | 154 | 155 | Upgrade all 156 | 157 | 158 | -------------------------------------------------------------------------------- /electron/src/pages/home/home.page.scss: -------------------------------------------------------------------------------- 1 | ion-content { 2 | //--background: #eceef3; 3 | --background: #18181b; 4 | } 5 | cdk-virtual-scroll-viewport { 6 | height: calc(100vh - 180px); 7 | width: 100%; 8 | max-width: 100%; 9 | background: #fff; 10 | border-radius: 5px; 11 | } 12 | ::ng-deep { 13 | .cdk-virtual-scroll-content-wrapper { 14 | right: 0; 15 | } 16 | } 17 | .item { 18 | height: 55px; 19 | width: 100%; 20 | .title { 21 | max-width: calc(100% - 60px); 22 | h2, 23 | p { 24 | text-overflow: ellipsis; 25 | overflow: hidden; 26 | width: 100%; 27 | height: 1.2em; 28 | white-space: nowrap; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /electron/src/pages/home/home.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { HomePage } from './home.page'; 5 | 6 | describe('HomePage', () => { 7 | let component: HomePage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(waitForAsync(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ HomePage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(HomePage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /electron/src/pages/home/home.page.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-empty */ 2 | /* eslint-disable @typescript-eslint/restrict-template-expressions */ 3 | /* eslint-disable no-async-promise-executor */ 4 | /* eslint-disable @typescript-eslint/no-misused-promises */ 5 | import { HttpClient } from '@angular/common/http'; 6 | import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; 7 | import { LoadingController, ToastController } from '@ionic/angular'; 8 | import { CommandService } from '../../app/core/services/command.service'; 9 | import { ElectronService } from '../../app/core/services/electron.service'; 10 | @Component({ 11 | selector: 'app-home', 12 | templateUrl: './home.page.html', 13 | styleUrls: ['./home.page.scss'], 14 | }) 15 | export class HomePage implements OnInit { 16 | packages; 17 | installed; 18 | search = ''; 19 | currentSearch = ''; 20 | 21 | mode = 'packages'; 22 | constructor( 23 | private commandService: CommandService, 24 | private loadingCtrl: LoadingController, 25 | private toastCtrl: ToastController, 26 | private http: HttpClient, 27 | private electronService: ElectronService, 28 | private cdr: ChangeDetectorRef 29 | ) {} 30 | 31 | async segmentChanged($event) { 32 | this.mode = $event.detail.value; 33 | await this.refresh(); 34 | } 35 | 36 | async refresh() { 37 | if (this.mode == 'installed') { 38 | await this.loadInstalled(); 39 | } 40 | if (this.mode == 'packages') { 41 | await this.loadPackages(); 42 | } 43 | } 44 | 45 | async ngOnInit() { 46 | await this.startUp(); 47 | } 48 | 49 | async startUp() { 50 | try { 51 | const checkWinget: any = await this.commandService.powershell('winget'); 52 | if (!checkWinget.includes('Windows Package Manager')) { 53 | await this.installWinGet(); 54 | } 55 | 56 | await this.refresh(); 57 | } catch (error) { 58 | await this.installWinGet(); 59 | await this.startUp(); 60 | console.log('checkWinget error', error); 61 | } 62 | } 63 | 64 | async installWinGet() { 65 | return new Promise(async (resolve, reject) => { 66 | const loading = await this.loadingCtrl.create({ 67 | message: 'Install WinGet ...', 68 | }); 69 | loading.present(); 70 | 71 | const data = await this.http 72 | .get('https://api.github.com/repos/microsoft/winget-cli/releases') 73 | .toPromise(); 74 | 75 | const latest = data[0]; 76 | const asset: any = latest.assets.find((asset) => 77 | asset.name.endsWith('.appxbundle') 78 | ); 79 | 80 | try { 81 | const tmp = this.electronService.app.getPath('temp'); 82 | 83 | await this.commandService.powershell( 84 | `Invoke-WebRequest -Uri ${asset.browser_download_url} -OutFile ${tmp}\\winget.appxbundle` 85 | ); 86 | await this.commandService.powershell( 87 | `Add-AppxPackage -Path "${tmp}\\winget.appxbundle"` 88 | ); 89 | loading.dismiss(); 90 | resolve(true); 91 | } catch (error) { 92 | loading.dismiss(); 93 | reject(error); 94 | } 95 | }); 96 | } 97 | 98 | async loadPackages() { 99 | this.packages = []; 100 | const loading = await this.loadingCtrl.create({ 101 | message: 'Load All Packages ...', 102 | }); 103 | loading.present(); 104 | 105 | try { 106 | let result: any = await this.commandService.powershell('winget install'); 107 | result = result.split('----------------------------------').pop(); 108 | result = result 109 | .split('\n') 110 | .map((lines: any) => { 111 | lines = lines 112 | .replace(/ +(?= )/g, '\t') 113 | .split('\t') 114 | .map((line) => line.trim()); 115 | return lines; 116 | }) 117 | .slice(1); 118 | 119 | this.packages = result; 120 | } catch (error) { 121 | } finally { 122 | loading.dismiss(); 123 | } 124 | } 125 | 126 | trackBy(index, item) { 127 | return item[0]; 128 | } 129 | 130 | async loadInstalled() { 131 | this.installed = []; 132 | const loading = await this.loadingCtrl.create({ 133 | message: 'Load Installed Packages ...', 134 | }); 135 | loading.present(); 136 | 137 | try { 138 | let result: any = await this.commandService.powershell('winget list'); 139 | result = result.split('----------------------------------').pop(); 140 | result = result 141 | .split('\n') 142 | .map((lines: any) => { 143 | lines = lines 144 | .replace(/ +(?= )/g, '\t') 145 | .split('\t') 146 | .map((line) => line.trim()); 147 | return lines; 148 | }) 149 | .slice(1); 150 | 151 | this.installed = result; 152 | } catch (error) { 153 | } finally { 154 | loading.dismiss(); 155 | } 156 | } 157 | 158 | async install(_package) { 159 | const loading = await this.loadingCtrl.create({ 160 | message: 'Package installing ...', 161 | }); 162 | try { 163 | loading.present(); 164 | await this.commandService.powershell(`winget install ${_package[1]}`); 165 | 166 | const toast = await this.toastCtrl.create({ 167 | duration: 5000, 168 | message: 'Package installed!', 169 | }); 170 | toast.present(); 171 | } catch (err) { 172 | const toast = await this.toastCtrl.create({ 173 | duration: 5000, 174 | message: 'Package not installed!', 175 | }); 176 | toast.present(); 177 | } finally { 178 | loading.dismiss(); 179 | } 180 | } 181 | 182 | async uninstall(_package) { 183 | const loading = await this.loadingCtrl.create({ 184 | message: 'Package uninstalling ...', 185 | }); 186 | try { 187 | loading.present(); 188 | await this.commandService.powershell(`winget uninstall ${_package[1]}`); 189 | 190 | const toast = await this.toastCtrl.create({ 191 | duration: 5000, 192 | message: 'Package uninstalled!', 193 | }); 194 | toast.present(); 195 | } catch (err) { 196 | const toast = await this.toastCtrl.create({ 197 | duration: 5000, 198 | message: 'Package not uninstalled!', 199 | }); 200 | toast.present(); 201 | } finally { 202 | loading.dismiss(); 203 | } 204 | } 205 | 206 | doSearch() { 207 | setTimeout(() => { 208 | this.currentSearch = this.search; 209 | this.cdr.detectChanges(); 210 | }, 50); 211 | } 212 | 213 | async upgradeAll() { 214 | const loading = await this.loadingCtrl.create({ 215 | message: 'Upgrading ...', 216 | }); 217 | try { 218 | loading.present(); 219 | await this.commandService.powershell(`winget upgrade --all`); 220 | 221 | const toast = await this.toastCtrl.create({ 222 | duration: 5000, 223 | message: 'Upgrading done!', 224 | }); 225 | toast.present(); 226 | } catch (err) { 227 | const toast = await this.toastCtrl.create({ 228 | duration: 5000, 229 | message: 'Upgrading failed!', 230 | }); 231 | toast.present(); 232 | } finally { 233 | loading.dismiss(); 234 | } 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /electron/src/pages/home/lazyFor.directive.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Input, 3 | Directive, 4 | ViewContainerRef, 5 | OnInit, 6 | TemplateRef, 7 | DoCheck, 8 | IterableDiffers, 9 | IterableDiffer, 10 | } from '@angular/core'; 11 | 12 | @Directive({ 13 | selector: '[lazyFor]', 14 | }) 15 | export class LazyForDirective implements DoCheck, OnInit { 16 | lazyForContainer: HTMLElement; 17 | 18 | itemHeight: number; 19 | itemTagName: string; 20 | 21 | @Input() 22 | set lazyForOf(list: any[]) { 23 | this.list = list; 24 | 25 | if (list) { 26 | this.differ = this.iterableDiffers.find(list).create(); 27 | 28 | if (this.initialized) { 29 | this.update(); 30 | } 31 | } 32 | } 33 | 34 | private templateElem: HTMLElement; 35 | 36 | private beforeListElem: HTMLElement; 37 | private afterListElem: HTMLElement; 38 | 39 | private list: any[] = []; 40 | 41 | private initialized = false; 42 | private firstUpdate = true; 43 | 44 | private differ: IterableDiffer; 45 | 46 | private lastChangeTriggeredByScroll = false; 47 | 48 | constructor( 49 | private vcr: ViewContainerRef, 50 | private tpl: TemplateRef, 51 | private iterableDiffers: IterableDiffers 52 | ) {} 53 | 54 | ngOnInit() { 55 | this.templateElem = this.vcr.element.nativeElement; 56 | 57 | this.lazyForContainer = this.templateElem.parentElement; 58 | 59 | //Adding an event listener will trigger ngDoCheck whenever the event fires so we don't actually need to call 60 | //update here. 61 | this.lazyForContainer.addEventListener('scroll', () => { 62 | this.lastChangeTriggeredByScroll = true; 63 | }); 64 | 65 | this.initialized = true; 66 | } 67 | 68 | ngDoCheck() { 69 | if (this.differ && Array.isArray(this.list)) { 70 | if (this.lastChangeTriggeredByScroll) { 71 | this.update(); 72 | this.lastChangeTriggeredByScroll = false; 73 | } else { 74 | const changes = this.differ.diff(this.list); 75 | 76 | if (changes !== null) { 77 | this.update(); 78 | } 79 | } 80 | } 81 | } 82 | 83 | /** 84 | * List update 85 | * 86 | * @returns {void} 87 | */ 88 | private update(): void { 89 | //Can't run the first update unless there is an element in the list 90 | if (this.list.length === 0) { 91 | this.vcr.clear(); 92 | if (!this.firstUpdate) { 93 | this.beforeListElem.style.height = '0'; 94 | this.afterListElem.style.height = '0'; 95 | } 96 | return; 97 | } 98 | 99 | if (this.firstUpdate) { 100 | this.onFirstUpdate(); 101 | } 102 | 103 | const listHeight = this.lazyForContainer.clientHeight; 104 | const scrollTop = this.lazyForContainer.scrollTop; 105 | 106 | //The height of anything inside the container but above the lazyFor content 107 | const fixedHeaderHeight = 108 | this.beforeListElem.getBoundingClientRect().top - 109 | this.beforeListElem.scrollTop - 110 | (this.lazyForContainer.getBoundingClientRect().top - 111 | this.lazyForContainer.scrollTop); 112 | 113 | //This needs to run after the scrollTop is retrieved. 114 | this.vcr.clear(); 115 | 116 | let listStartI = Math.floor( 117 | (scrollTop - fixedHeaderHeight) / this.itemHeight 118 | ); 119 | listStartI = this.limitToRange(listStartI, 0, this.list.length); 120 | 121 | let listEndI = Math.ceil( 122 | (scrollTop - fixedHeaderHeight + listHeight) / this.itemHeight 123 | ); 124 | listEndI = this.limitToRange(listEndI, -1, this.list.length - 1); 125 | 126 | for (let i = listStartI; i <= listEndI; i++) { 127 | this.vcr.createEmbeddedView(this.tpl, { 128 | $implicit: this.list[i], 129 | index: i, 130 | }); 131 | } 132 | 133 | this.beforeListElem.style.height = `${listStartI * this.itemHeight}px`; 134 | this.afterListElem.style.height = `${ 135 | (this.list.length - listEndI - 1) * this.itemHeight 136 | }px`; 137 | } 138 | 139 | /** 140 | * First update. 141 | * 142 | * @returns {void} 143 | */ 144 | private onFirstUpdate(): void { 145 | let sampleItemElem: HTMLElement; 146 | if (this.itemHeight === undefined || this.itemTagName === undefined) { 147 | this.vcr.createEmbeddedView(this.tpl, { 148 | $implicit: this.list[0], 149 | index: 0, 150 | }); 151 | sampleItemElem = this.templateElem.nextSibling; 152 | } 153 | 154 | if (this.itemHeight === undefined) { 155 | this.itemHeight = sampleItemElem.clientHeight; 156 | } 157 | 158 | if (this.itemTagName === undefined) { 159 | this.itemTagName = sampleItemElem.tagName; 160 | } 161 | 162 | this.beforeListElem = document.createElement(this.itemTagName); 163 | this.templateElem.parentElement.insertBefore( 164 | this.beforeListElem, 165 | this.templateElem 166 | ); 167 | 168 | this.afterListElem = document.createElement(this.itemTagName); 169 | this.templateElem.parentElement.insertBefore( 170 | this.afterListElem, 171 | this.templateElem.nextSibling 172 | ); 173 | 174 | // this.firstUpdate = false; 175 | } 176 | 177 | /** 178 | * Limit To Range 179 | * 180 | * @param {number} num - Element number. 181 | * @param {number} min - Min element number. 182 | * @param {number} max - Max element number. 183 | * 184 | * @returns {number} 185 | */ 186 | private limitToRange(num: number, min: number, max: number) { 187 | return Math.max(Math.min(num, max), min); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /electron/src/pages/home/number.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, HostListener, ElementRef } from "@angular/core"; 2 | 3 | @Directive({ 4 | selector: "[number-format]", 5 | }) 6 | export class NumberDirective { 7 | @HostListener("input", ["$event"]) 8 | onKeyDown(event: KeyboardEvent) { 9 | const input = event.target as HTMLInputElement; 10 | 11 | let trimmed = input.value.replace(/\s+/g, ""); 12 | if (trimmed.length > 16) { 13 | trimmed = trimmed.substr(0, 16); 14 | } 15 | 16 | let numbers = []; 17 | for (let i = 0; i < trimmed.length; i += 4) { 18 | numbers.push(trimmed.substr(i, 4)); 19 | } 20 | 21 | input.value = numbers.join(" "); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /electron/src/pages/settings/settings-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { SettingsPage } from './settings.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: SettingsPage 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule], 16 | }) 17 | export class SettingsPageRoutingModule {} 18 | -------------------------------------------------------------------------------- /electron/src/pages/settings/settings.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { MatButtonModule } from '@angular/material/button'; 5 | import { MatDialogModule } from '@angular/material/dialog'; 6 | import { MatInputModule } from '@angular/material/input'; 7 | import { MatSnackBarModule } from '@angular/material/snack-bar'; 8 | import { IonicModule } from '@ionic/angular'; 9 | import { TranslateModule } from '@ngx-translate/core'; 10 | import { SettingsPageRoutingModule } from './settings-routing.module'; 11 | import { SettingsPage } from './settings.page'; 12 | 13 | @NgModule({ 14 | imports: [ 15 | CommonModule, 16 | FormsModule, 17 | IonicModule, 18 | SettingsPageRoutingModule, 19 | MatInputModule, 20 | MatDialogModule, 21 | MatButtonModule, 22 | TranslateModule, 23 | MatSnackBarModule, 24 | ], 25 | declarations: [SettingsPage], 26 | }) 27 | export class SettingsPageModule {} 28 | -------------------------------------------------------------------------------- /electron/src/pages/settings/settings.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{'Settings'| translate}} 7 | 8 | 9 | 10 | 11 |
24 | 25 | 30 | {{'Autostart' |translate}} 31 | 32 | 33 | 39 | {{'Language' |translate}} 40 | 41 | 45 | 49 | 50 | 51 |
52 |
53 | -------------------------------------------------------------------------------- /electron/src/pages/settings/settings.page.scss: -------------------------------------------------------------------------------- 1 | .language { 2 | img { 3 | max-height: 25px; 4 | } 5 | span { 6 | display: flex; 7 | align-items: center; 8 | justify-content: center; 9 | height: 100%; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /electron/src/pages/settings/settings.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { SettingsPage } from './settings.page'; 5 | 6 | describe('SettingsPage', () => { 7 | let component: SettingsPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(waitForAsync(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ SettingsPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(SettingsPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /electron/src/pages/settings/settings.page.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { Component, OnInit } from '@angular/core'; 3 | import { MatDialog } from '@angular/material/dialog'; 4 | import { ActionSheetController } from '@ionic/angular'; 5 | import { TranslateService } from '@ngx-translate/core'; 6 | import { ElectronService } from '../../app/core/services/electron.service'; 7 | import { SettingsService } from '../../app/core/services/settings.service'; 8 | 9 | @Component({ 10 | selector: 'app-settings', 11 | templateUrl: './settings.page.html', 12 | styleUrls: ['./settings.page.scss'], 13 | }) 14 | export class SettingsPage implements OnInit { 15 | autoStartEnabled = false; 16 | autoLaunch; 17 | 18 | hiddenAccess = false; 19 | 20 | constructor( 21 | private electronService: ElectronService, 22 | public dialog: MatDialog, 23 | private translate: TranslateService, 24 | private actionSheetCtrl: ActionSheetController, 25 | public settingsService: SettingsService 26 | ) {} 27 | 28 | ngOnInit() { 29 | const loginSettings = this.electronService.app.getLoginItemSettings(); 30 | 31 | this.autoStartEnabled = loginSettings.executableWillLaunchAtLogin; 32 | } 33 | 34 | async checkForUpdates() { 35 | console.log( 36 | 'this.electronService.autoUpdater', 37 | this.electronService.autoUpdater.autoUpdater 38 | ); 39 | await this.electronService.autoUpdater.autoUpdater.checkForUpdates(); 40 | } 41 | 42 | public async selectLanguage(ev): Promise { 43 | const actionSheetCtrl = await this.actionSheetCtrl.create({ 44 | translucent: true, 45 | buttons: [ 46 | { 47 | text: 'Deutsch', 48 | handler: () => { 49 | this.changeLanguage({ code: 'de', text: 'Deutsch' }); 50 | }, 51 | }, 52 | { 53 | text: 'English', 54 | handler: () => { 55 | this.changeLanguage({ code: 'en', text: 'English' }); 56 | }, 57 | }, 58 | ], 59 | }); 60 | 61 | await actionSheetCtrl.present(); 62 | } 63 | 64 | async changeLanguage(selection: { text: string; code: string }) { 65 | await this.settingsService.saveSettings({ 66 | language: selection, 67 | }); 68 | 69 | this.settingsService.language = selection; 70 | this.translate.use(selection.code); 71 | } 72 | 73 | changeAutoStart() { 74 | if (this.autoStartEnabled) { 75 | this.electronService.app.setLoginItemSettings({ 76 | openAsHidden: true, 77 | openAtLogin: true, 78 | name: 'Windows Package Manager GUI', 79 | args: ['--hidden'], 80 | }); 81 | } else { 82 | this.electronService.app.setLoginItemSettings({ 83 | openAsHidden: false, 84 | openAtLogin: false, 85 | name: 'Windows Package Manager GUI', 86 | args: ['--hidden'], 87 | }); 88 | } 89 | /*this.autoLaunch.isEnabled().then((isEnabled) => { 90 | if (isEnabled) { 91 | this.autoLaunch.disable(); 92 | } else { 93 | this.autoLaunch.enable(); 94 | } 95 | });*/ 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /electron/src/polyfills-test.ts: -------------------------------------------------------------------------------- 1 | import 'core-js/es/reflect'; 2 | import 'zone.js/dist/zone'; 3 | -------------------------------------------------------------------------------- /electron/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | /*************************************************************************************************** 56 | * Zone JS is required by default for Angular itself. 57 | */ 58 | import 'zone.js/dist/zone'; // Included with Angular CLI. 59 | 60 | /*************************************************************************************************** 61 | * APPLICATION IMPORTS 62 | */ 63 | (window as any)['global'] = window; 64 | -------------------------------------------------------------------------------- /electron/src/styles.scss: -------------------------------------------------------------------------------- 1 | @import 'tailwindcss/base'; 2 | @import 'tailwindcss/components'; 3 | @import 'tailwindcss/utilities'; 4 | 5 | @import '@ionic/angular/css/core.css'; 6 | 7 | @import '@ionic/angular/css/normalize.css'; 8 | @import '@ionic/angular/css/structure.css'; 9 | @import '@ionic/angular/css/typography.css'; 10 | @import '@ionic/angular/css/display.css'; 11 | 12 | @import '@ionic/angular/css/padding.css'; 13 | @import '@ionic/angular/css/float-elements.css'; 14 | @import '@ionic/angular/css/text-alignment.css'; 15 | @import '@ionic/angular/css/text-transformation.css'; 16 | @import '@ionic/angular/css/flex-utils.css'; 17 | 18 | @import '~@angular/material/theming'; 19 | @import '~@angular/material/prebuilt-themes/indigo-pink.css'; 20 | 21 | $mdPrimary: ( 22 | 50: #e2eaf2, 23 | 100: #b6cbdf, 24 | 200: #85a9ca, 25 | 300: #5487b4, 26 | 400: #306da4, 27 | 500: #0b5394, 28 | 600: #0a4c8c, 29 | 700: #084281, 30 | 800: #063977, 31 | 900: #032965, 32 | A100: #95b6ff, 33 | A200: #6294ff, 34 | A400: #2f71ff, 35 | A700: #155fff, 36 | contrast: ( 37 | 50: #000000, 38 | 100: #000000, 39 | 200: #000000, 40 | 300: #ffffff, 41 | 400: #ffffff, 42 | 500: #ffffff, 43 | 600: #ffffff, 44 | 700: #ffffff, 45 | 800: #ffffff, 46 | 900: #ffffff, 47 | A100: #000000, 48 | A200: #000000, 49 | A400: #ffffff, 50 | A700: #ffffff, 51 | ), 52 | ); 53 | $md-mcgpalette0: ( 54 | 50: #e2eaf2, 55 | 100: #b6cbdf, 56 | 200: #85a9ca, 57 | 300: #5487b4, 58 | 400: #306da4, 59 | 500: #0b5394, 60 | 600: #0a4c8c, 61 | 700: #084281, 62 | 800: #063977, 63 | 900: #032965, 64 | A100: #95b6ff, 65 | A200: #6294ff, 66 | A400: #2f71ff, 67 | A700: #155fff, 68 | contrast: ( 69 | 50: #000000, 70 | 100: #000000, 71 | 200: #000000, 72 | 300: #ffffff, 73 | 400: #ffffff, 74 | 500: #ffffff, 75 | 600: #ffffff, 76 | 700: #ffffff, 77 | 800: #ffffff, 78 | 900: #ffffff, 79 | A100: #000000, 80 | A200: #000000, 81 | A400: #ffffff, 82 | A700: #ffffff, 83 | ), 84 | ); 85 | 86 | $primary: mat-palette($mdPrimary); 87 | $accent: mat-palette($md-mcgpalette0); 88 | $theme: mat-light-theme($primary, $accent); 89 | 90 | @include angular-material-theme($theme); 91 | 92 | @media (prefers-color-scheme: dark) { 93 | @include angular-material-theme($theme); 94 | } 95 | 96 | [type='text']:focus, 97 | [type='email']:focus, 98 | [type='url']:focus, 99 | [type='password']:focus, 100 | [type='number']:focus, 101 | [type='date']:focus, 102 | [type='datetime-local']:focus, 103 | [type='month']:focus, 104 | [type='search']:focus, 105 | [type='tel']:focus, 106 | [type='time']:focus, 107 | [type='week']:focus, 108 | [multiple]:focus, 109 | textarea:focus, 110 | select:focus { 111 | --tw-ring-color: transparent; 112 | } 113 | 114 | input:focus { 115 | outline: none; 116 | } 117 | 118 | button { 119 | outline: none; 120 | &:focus { 121 | outline: none; 122 | } 123 | } 124 | ion-item { 125 | ion-label { 126 | white-space: pre-wrap !important; 127 | } 128 | } 129 | ion-button { 130 | text-transform: none !important; 131 | } 132 | 133 | ion-item { 134 | border-radius: 10px; 135 | } 136 | 137 | ion-content { 138 | & { 139 | ::-webkit-scrollbar { 140 | width: 12px; 141 | display: block !important; 142 | } 143 | 144 | ::-webkit-scrollbar-track { 145 | background: rgba(0, 0, 0, 0.1); 146 | display: block !important; 147 | } 148 | 149 | ::-webkit-scrollbar-thumb { 150 | border-radius: 10px; 151 | background: rgba(0, 0, 0, 0.5); 152 | display: block !important; 153 | } 154 | } 155 | } 156 | 157 | ion-segment-button { 158 | text-transform: none; 159 | } 160 | 161 | ion-app { 162 | top: 30px !important; 163 | max-height: calc(100% - 30px); 164 | } 165 | 166 | /** Ionic CSS Variables **/ 167 | :root { 168 | --card-border-radius: 3px; 169 | --card-box-shadow: 0 3px 6px rgba(0, 0, 0, 0.35); 170 | /** primary **/ 171 | --ion-color-primary: #252a33; 172 | --ion-color-primary-rgb: 37, 42, 51; 173 | --ion-color-primary-contrast: #ffffff; 174 | --ion-color-primary-contrast-rgb: 255, 255, 255; 175 | --ion-color-primary-shade: #21252d; 176 | --ion-color-primary-tint: #3b3f47; 177 | /** secondary **/ 178 | --ion-color-secondary: #06d79c; 179 | --ion-color-secondary-rgb: 50, 219, 100; 180 | --ion-color-secondary-contrast: #fff; 181 | --ion-color-secondary-contrast-rgb: 255, 255, 255; 182 | --ion-color-secondary-shade: #04b381; 183 | --ion-color-secondary-tint: #47df74; 184 | 185 | /** tertiary **/ 186 | --ion-color-tertiary: #f4a942; 187 | --ion-color-tertiary-rgb: 244, 169, 66; 188 | --ion-color-tertiary-contrast: #fff; 189 | --ion-color-tertiary-contrast-rgb: 255, 255, 255; 190 | --ion-color-tertiary-shade: #d7953a; 191 | --ion-color-tertiary-tint: #f5b255; 192 | 193 | /** success **/ 194 | --ion-color-success: #10dc60; 195 | --ion-color-success-rgb: 16, 220, 96; 196 | --ion-color-success-contrast: #fff; 197 | --ion-color-success-contrast-rgb: 255, 255, 255; 198 | --ion-color-success-shade: #0ec254; 199 | --ion-color-success-tint: #28e070; 200 | 201 | /** warning **/ 202 | --ion-color-warning: #ffce00; 203 | --ion-color-warning-rgb: 255, 206, 0; 204 | --ion-color-warning-contrast: #000; 205 | --ion-color-warning-contrast-rgb: 0, 0, 0; 206 | --ion-color-warning-shade: #e0b500; 207 | --ion-color-warning-tint: #ffd31a; 208 | 209 | /** danger **/ 210 | --ion-color-danger: #f53d3d; 211 | --ion-color-danger-rgb: 245, 61, 61; 212 | --ion-color-danger-contrast: #fff; 213 | --ion-color-danger-contrast-rgb: 255, 255, 255; 214 | --ion-color-danger-shade: #d83636; 215 | --ion-color-danger-tint: #f65050; 216 | 217 | /** light **/ 218 | --ion-color-light: #f4f4f4; 219 | --ion-color-light-rgb: 244, 244, 244; 220 | --ion-color-light-contrast: #000; 221 | --ion-color-light-contrast-rgb: 0, 0, 0; 222 | --ion-color-light-shade: #d7d7d7; 223 | --ion-color-light-tint: #f5f5f5; 224 | 225 | /** medium **/ 226 | --ion-color-medium: #989aa2; 227 | --ion-color-medium-rgb: 152, 154, 162; 228 | --ion-color-medium-contrast: #000; 229 | --ion-color-medium-contrast-rgb: 0, 0, 0; 230 | --ion-color-medium-shade: #86888f; 231 | --ion-color-medium-tint: #a2a4ab; 232 | 233 | /** dark **/ 234 | --ion-color-dark: #455a64; 235 | --ion-color-dark-rgb: 34, 34, 34; 236 | --ion-color-dark-contrast: #fff; 237 | --ion-color-dark-contrast-rgb: 255, 255, 255; 238 | --ion-color-dark-shade: #455a64; 239 | --ion-color-dark-tint: #455a64; 240 | } 241 | 242 | @media (prefers-color-scheme: light) { 243 | /* 244 | * Dark Colors 245 | * ------------------------------------------- 246 | */ 247 | 248 | body { 249 | --ion-color-primary: #252a33; 250 | --ion-color-primary-rgb: 37, 42, 51; 251 | --ion-color-primary-contrast: #ffffff; 252 | --ion-color-primary-contrast-rgb: 255, 255, 255; 253 | --ion-color-primary-shade: #21252d; 254 | --ion-color-primary-tint: #3b3f47; 255 | 256 | --ion-color-secondary: #50c8ff; 257 | --ion-color-secondary-rgb: 80, 200, 255; 258 | --ion-color-secondary-contrast: #ffffff; 259 | --ion-color-secondary-contrast-rgb: 255, 255, 255; 260 | --ion-color-secondary-shade: #46b0e0; 261 | --ion-color-secondary-tint: #62ceff; 262 | 263 | --ion-color-tertiary: #6a64ff; 264 | --ion-color-tertiary-rgb: 106, 100, 255; 265 | --ion-color-tertiary-contrast: #ffffff; 266 | --ion-color-tertiary-contrast-rgb: 255, 255, 255; 267 | --ion-color-tertiary-shade: #5d58e0; 268 | --ion-color-tertiary-tint: #7974ff; 269 | 270 | --ion-color-success: #2fdf75; 271 | --ion-color-success-rgb: 47, 223, 117; 272 | --ion-color-success-contrast: #000000; 273 | --ion-color-success-contrast-rgb: 0, 0, 0; 274 | --ion-color-success-shade: #29c467; 275 | --ion-color-success-tint: #44e283; 276 | 277 | --ion-color-warning: #ffd534; 278 | --ion-color-warning-rgb: 255, 213, 52; 279 | --ion-color-warning-contrast: #000000; 280 | --ion-color-warning-contrast-rgb: 0, 0, 0; 281 | --ion-color-warning-shade: #e0bb2e; 282 | --ion-color-warning-tint: #ffd948; 283 | 284 | --ion-color-danger: #ff4961; 285 | --ion-color-danger-rgb: 255, 73, 97; 286 | --ion-color-danger-contrast: #ffffff; 287 | --ion-color-danger-contrast-rgb: 255, 255, 255; 288 | --ion-color-danger-shade: #e04055; 289 | --ion-color-danger-tint: #ff5b71; 290 | 291 | --ion-color-dark: #f4f5f8; 292 | --ion-color-dark-rgb: 244, 245, 248; 293 | --ion-color-dark-contrast: #000000; 294 | --ion-color-dark-contrast-rgb: 0, 0, 0; 295 | --ion-color-dark-shade: #d7d8da; 296 | --ion-color-dark-tint: #f5f6f9; 297 | 298 | --ion-color-medium: #989aa2; 299 | --ion-color-medium-rgb: 152, 154, 162; 300 | --ion-color-medium-contrast: #000000; 301 | --ion-color-medium-contrast-rgb: 0, 0, 0; 302 | --ion-color-medium-shade: #86888f; 303 | --ion-color-medium-tint: #a2a4ab; 304 | 305 | --ion-color-light: #222428; 306 | --ion-color-light-rgb: 34, 36, 40; 307 | --ion-color-light-contrast: #ffffff; 308 | --ion-color-light-contrast-rgb: 255, 255, 255; 309 | --ion-color-light-shade: #1e2023; 310 | --ion-color-light-tint: #383a3e; 311 | } 312 | } 313 | /* 314 | * Dark Colors 315 | * ------------------------------------------- 316 | */ 317 | body { 318 | ion-content { 319 | --background: #f4f6f9; 320 | } 321 | } 322 | body.dark { 323 | ion-content { 324 | --background: #000; 325 | } 326 | ion-list { 327 | border-top: 1px solid #333; 328 | border-bottom: 1px solid #333; 329 | 330 | ion-item { 331 | --background: #1c1c1e; 332 | --border-color: #333; 333 | } 334 | } 335 | --ion-color-primary: #252a33; 336 | --ion-color-primary-rgb: 37, 42, 51; 337 | --ion-color-primary-contrast: #ffffff; 338 | --ion-color-primary-contrast-rgb: 255, 255, 255; 339 | --ion-color-primary-shade: #21252d; 340 | --ion-color-primary-tint: #3b3f47; 341 | 342 | --ion-color-secondary: #50c8ff; 343 | --ion-color-secondary-rgb: 80, 200, 255; 344 | --ion-color-secondary-contrast: #ffffff; 345 | --ion-color-secondary-contrast-rgb: 255, 255, 255; 346 | --ion-color-secondary-shade: #46b0e0; 347 | --ion-color-secondary-tint: #62ceff; 348 | 349 | --ion-color-tertiary: #6a64ff; 350 | --ion-color-tertiary-rgb: 106, 100, 255; 351 | --ion-color-tertiary-contrast: #ffffff; 352 | --ion-color-tertiary-contrast-rgb: 255, 255, 255; 353 | --ion-color-tertiary-shade: #5d58e0; 354 | --ion-color-tertiary-tint: #7974ff; 355 | 356 | --ion-color-success: #2fdf75; 357 | --ion-color-success-rgb: 47, 223, 117; 358 | --ion-color-success-contrast: #000000; 359 | --ion-color-success-contrast-rgb: 0, 0, 0; 360 | --ion-color-success-shade: #29c467; 361 | --ion-color-success-tint: #44e283; 362 | 363 | --ion-color-warning: #ffd534; 364 | --ion-color-warning-rgb: 255, 213, 52; 365 | --ion-color-warning-contrast: #000000; 366 | --ion-color-warning-contrast-rgb: 0, 0, 0; 367 | --ion-color-warning-shade: #e0bb2e; 368 | --ion-color-warning-tint: #ffd948; 369 | 370 | --ion-color-danger: #ff4961; 371 | --ion-color-danger-rgb: 255, 73, 97; 372 | --ion-color-danger-contrast: #ffffff; 373 | --ion-color-danger-contrast-rgb: 255, 255, 255; 374 | --ion-color-danger-shade: #e04055; 375 | --ion-color-danger-tint: #ff5b71; 376 | 377 | --ion-color-dark: #f4f5f8; 378 | --ion-color-dark-rgb: 244, 245, 248; 379 | --ion-color-dark-contrast: #000000; 380 | --ion-color-dark-contrast-rgb: 0, 0, 0; 381 | --ion-color-dark-shade: #d7d8da; 382 | --ion-color-dark-tint: #f5f6f9; 383 | 384 | --ion-color-medium: #989aa2; 385 | --ion-color-medium-rgb: 152, 154, 162; 386 | --ion-color-medium-contrast: #000000; 387 | --ion-color-medium-contrast-rgb: 0, 0, 0; 388 | --ion-color-medium-shade: #86888f; 389 | --ion-color-medium-tint: #a2a4ab; 390 | 391 | --ion-color-light: #222428; 392 | --ion-color-light-rgb: 34, 36, 40; 393 | --ion-color-light-contrast: #ffffff; 394 | --ion-color-light-contrast-rgb: 255, 255, 255; 395 | --ion-color-light-shade: #1e2023; 396 | --ion-color-light-tint: #383a3e; 397 | } 398 | 399 | /* 400 | * iOS Dark Theme 401 | * ------------------------------------------- 402 | */ 403 | 404 | .ios body.dark { 405 | --ion-background-color: #000000; 406 | --ion-background-color-rgb: 0, 0, 0; 407 | 408 | --ion-text-color: #ffffff; 409 | --ion-text-color-rgb: 255, 255, 255; 410 | 411 | --ion-color-step-50: #0d0d0d; 412 | --ion-color-step-100: #1a1a1a; 413 | --ion-color-step-150: #262626; 414 | --ion-color-step-200: #333333; 415 | --ion-color-step-250: #404040; 416 | --ion-color-step-300: #4d4d4d; 417 | --ion-color-step-350: #595959; 418 | --ion-color-step-400: #666666; 419 | --ion-color-step-450: #737373; 420 | --ion-color-step-500: #808080; 421 | --ion-color-step-550: #8c8c8c; 422 | --ion-color-step-600: #999999; 423 | --ion-color-step-650: #a6a6a6; 424 | --ion-color-step-700: #b3b3b3; 425 | --ion-color-step-750: #bfbfbf; 426 | --ion-color-step-800: #cccccc; 427 | --ion-color-step-850: #d9d9d9; 428 | --ion-color-step-900: #e6e6e6; 429 | --ion-color-step-950: #f2f2f2; 430 | 431 | --ion-toolbar-background: #0d0d0d; 432 | 433 | --ion-item-background: #000000; 434 | } 435 | 436 | /* 437 | * Material Design Dark Theme 438 | * ------------------------------------------- 439 | */ 440 | 441 | .md body.dark { 442 | --ion-background-color: #121212; 443 | --ion-background-color-rgb: 18, 18, 18; 444 | 445 | --ion-text-color: #ffffff; 446 | --ion-text-color-rgb: 255, 255, 255; 447 | 448 | --ion-border-color: #222222; 449 | 450 | --ion-color-step-50: #1e1e1e; 451 | --ion-color-step-100: #2a2a2a; 452 | --ion-color-step-150: #363636; 453 | --ion-color-step-200: #414141; 454 | --ion-color-step-250: #4d4d4d; 455 | --ion-color-step-300: #595959; 456 | --ion-color-step-350: #656565; 457 | --ion-color-step-400: #717171; 458 | --ion-color-step-450: #7d7d7d; 459 | --ion-color-step-500: #898989; 460 | --ion-color-step-550: #949494; 461 | --ion-color-step-600: #a0a0a0; 462 | --ion-color-step-650: #acacac; 463 | --ion-color-step-700: #b8b8b8; 464 | --ion-color-step-750: #c4c4c4; 465 | --ion-color-step-800: #d0d0d0; 466 | --ion-color-step-850: #dbdbdb; 467 | --ion-color-step-900: #e7e7e7; 468 | --ion-color-step-950: #f3f3f3; 469 | 470 | --ion-item-background: #1e1e1e; 471 | 472 | --ion-toolbar-background: #1f1f1f; 473 | 474 | --ion-tab-bar-background: #1f1f1f; 475 | } 476 | -------------------------------------------------------------------------------- /electron/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /electron/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "es2015", 6 | "baseUrl": "", 7 | "types": [] 8 | }, 9 | "include": [ 10 | "main.ts", 11 | "polyfills.ts", 12 | "app/**/*.ts", 13 | "environments/**/*.ts" 14 | ], 15 | "exclude": [ 16 | "**/*.spec.ts" 17 | ], 18 | "angularCompilerOptions": { 19 | "fullTemplateTypeCheck": true, 20 | "strictInjectionParameters": true, 21 | "preserveWhitespaces": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /electron/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "module": "commonjs", 6 | "types": [ 7 | "jasmine", 8 | "node" 9 | ] 10 | }, 11 | "files": [ 12 | "test.ts", 13 | "polyfills-test.ts" 14 | ], 15 | "include": [ 16 | "**/*.spec.ts", 17 | "**/*.d.ts" 18 | ], 19 | "exclude": [ 20 | "dist", 21 | "release", 22 | "node_modules" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /electron/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare const nodeModule: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | interface Window { 7 | process: any; 8 | require: any; 9 | } 10 | -------------------------------------------------------------------------------- /electron/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const colors = require('tailwindcss/colors'); 2 | 3 | module.exports = { 4 | purge: ['./src/**/*.{html,ts}'], 5 | darkMode: false, // or 'media' or 'class' 6 | theme: { 7 | extend: {}, 8 | }, 9 | variants: { 10 | extend: {}, 11 | }, 12 | corePlugins: { 13 | outline: false, 14 | accessibility: false, 15 | }, 16 | plugins: [], 17 | }; 18 | -------------------------------------------------------------------------------- /electron/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "allowSyntheticDefaultImports": true, 5 | "outDir": "./dist/out-tsc", 6 | 7 | "sourceMap": true, 8 | "declaration": false, 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "allowJs": true, 13 | "target": "es2015", 14 | "module": "es2020", 15 | "typeRoots": ["node_modules/@types"], 16 | "lib": ["es2017", "es2016", "es2015", "dom"], 17 | "skipLibCheck": true 18 | }, 19 | "angularCompilerOptions": { 20 | "enableI18nLegacyMessageIdFormat": false, 21 | "strictInjectionParameters": true, 22 | "strictInputAccessModifiers": true, 23 | "strictTemplates": true 24 | }, 25 | "include": ["src/**/*.d.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /electron/tsconfig.serve.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "declaration": false, 5 | "moduleResolution": "node", 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "target": "es5", 9 | "types": [ 10 | "node" 11 | ], 12 | "lib": [ 13 | "es2017", 14 | "es2016", 15 | "es2015", 16 | "dom" 17 | ] 18 | }, 19 | "files": [ 20 | "main.ts" 21 | ], 22 | "exclude": [ 23 | "node_modules", 24 | "**/*.spec.ts" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "winget-gui", 3 | "private": true, 4 | "version": "0.1.7", 5 | "type": "module", 6 | "scripts": { 7 | "tauri": "tauri", 8 | "tauri:dev": "tauri dev", 9 | "ng": "ng", 10 | "dev": "ng serve --port 1420", 11 | "build": "ng build", 12 | "watch": "ng build --watch --configuration development" 13 | }, 14 | "dependencies": { 15 | "@angular/animations": "^15.0.4", 16 | "@angular/common": "^15.0.4", 17 | "@angular/compiler": "^15.0.4", 18 | "@angular/core": "^15.0.4", 19 | "@angular/forms": "^15.0.4", 20 | "@angular/platform-browser": "^15.0.4", 21 | "@angular/platform-browser-dynamic": "^15.0.4", 22 | "@angular/router": "^15.0.4", 23 | "@ngneat/hot-toast": "^4.1.0", 24 | "@ngneat/overview": "^3.0.4", 25 | "@tauri-apps/api": "^1.2.0", 26 | "autoprefixer": "^10.4.13", 27 | "daisyui": "^2.46.0", 28 | "ng2-search-filter": "^0.5.1", 29 | "postcss": "^8.4.20", 30 | "rxjs": "~7.8.0", 31 | "tailwindcss": "^3.2.4", 32 | "tslib": "^2.4.1", 33 | "zone.js": "~0.12.0" 34 | }, 35 | "devDependencies": { 36 | "@angular-devkit/build-angular": "^15.0.4", 37 | "@angular/cli": "~15.0.4", 38 | "@angular/compiler-cli": "^15.0.4", 39 | "@tauri-apps/cli": "^1.2.2", 40 | "typescript": "~4.8.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src-tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | -------------------------------------------------------------------------------- /src-tauri/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "winget-gui" 3 | version = "0.0.0" 4 | description = "A Tauri App" 5 | authors = ["you"] 6 | license = "" 7 | repository = "" 8 | edition = "2021" 9 | rust-version = "1.57" 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | 13 | [build-dependencies] 14 | tauri-build = { version = "1.2", features = [] } 15 | 16 | [dependencies] 17 | serde_json = "1.0" 18 | serde = { version = "1.0", features = ["derive"] } 19 | tauri = { version = "1.2", features = ["shell-all"] } 20 | window-vibrancy = "0.3.2" 21 | 22 | [features] 23 | # by default Tauri runs in production mode 24 | # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL 25 | default = ["custom-protocol"] 26 | # this feature is used used for production builds where `devPath` points to the filesystem 27 | # DO NOT remove this 28 | custom-protocol = ["tauri/custom-protocol"] 29 | -------------------------------------------------------------------------------- /src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build() 3 | } 4 | -------------------------------------------------------------------------------- /src-tauri/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/128x128.png -------------------------------------------------------------------------------- /src-tauri/icons/128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/128x128@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/32x32.png -------------------------------------------------------------------------------- /src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /src-tauri/src/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr( 2 | all(not(debug_assertions), target_os = "windows"), 3 | windows_subsystem = "windows" 4 | )] 5 | 6 | fn main() { 7 | tauri::Builder::default() 8 | .run(tauri::generate_context!()) 9 | .expect("error while running tauri application"); 10 | } 11 | -------------------------------------------------------------------------------- /src-tauri/tauri.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "beforeDevCommand": "yarn dev", 4 | "beforeBuildCommand": "yarn build", 5 | "devPath": "http://localhost:1420", 6 | "distDir": "../dist", 7 | "withGlobalTauri": false 8 | }, 9 | "package": { 10 | "productName": "winget-gui", 11 | "version": "0.1.7" 12 | }, 13 | "tauri": { 14 | "allowlist": { 15 | "all": false, 16 | "shell": { 17 | "all": true, 18 | "execute": true, 19 | "sidecar": true, 20 | "open": true, 21 | "scope": [ 22 | { 23 | "name": "powershell", 24 | "cmd": "powershell", 25 | "args": true 26 | } 27 | ] 28 | } 29 | }, 30 | "bundle": { 31 | "active": true, 32 | "category": "DeveloperTool", 33 | "copyright": "", 34 | "deb": { 35 | "depends": [] 36 | }, 37 | "externalBin": [], 38 | "icon": [ 39 | "icons/32x32.png", 40 | "icons/128x128.png", 41 | "icons/128x128@2x.png", 42 | "icons/icon.icns", 43 | "icons/icon.ico" 44 | ], 45 | "identifier": "de.codext.winget-gui", 46 | "longDescription": "", 47 | "resources": [], 48 | "shortDescription": "", 49 | "targets": "all", 50 | "windows": { 51 | "certificateThumbprint": null, 52 | "digestAlgorithm": "sha256", 53 | "timestampUrl": "" 54 | } 55 | }, 56 | "security": { 57 | "csp": "default-src 'self'; img-src 'self';" 58 | }, 59 | "updater": { 60 | "active": false 61 | }, 62 | "windows": [ 63 | { 64 | "fullscreen": false, 65 | "height": 600, 66 | "resizable": true, 67 | "title": "Winget GUI", 68 | "width": 600 69 | } 70 | ] 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { HttpClient, HttpClientModule } from "@angular/common/http"; 3 | import { ChangeDetectorRef, Component } from "@angular/core"; 4 | import { FormsModule } from "@angular/forms"; 5 | import { HotToastModule, HotToastService } from "@ngneat/hot-toast"; 6 | import { Command } from "@tauri-apps/api/shell"; 7 | import { Ng2SearchPipeModule } from "ng2-search-filter"; 8 | 9 | @Component({ 10 | selector: "app-root", 11 | template: ` 12 |
13 | 20 |
21 | 25 |
36 |
37 |

{{ package[0] }}

38 |

39 | {{ package[1] }} - {{ package[2] }} 40 |

41 |
42 | 43 | 52 | 53 |
54 | 62 | 63 | 71 |
72 |
73 |
74 |
75 | `, 76 | 77 | standalone: true, 78 | imports: [ 79 | HttpClientModule, 80 | CommonModule, 81 | FormsModule, 82 | Ng2SearchPipeModule, 83 | HotToastModule, 84 | ], 85 | }) 86 | export class AppComponent { 87 | packages: any; 88 | installed: any; 89 | search = ""; 90 | currentSearch = ""; 91 | mode = "packages"; 92 | loading = true; 93 | 94 | constructor( 95 | private http: HttpClient, 96 | private cdr: ChangeDetectorRef, 97 | private toast: HotToastService 98 | ) {} 99 | 100 | async ngOnInit() { 101 | await this.startUp(); 102 | } 103 | 104 | async startUp() { 105 | this.loading = true; 106 | try { 107 | const checkWinget: any = await this.powershell("winget"); 108 | if (checkWinget.includes("winget")) { 109 | await this.loadPackages(); 110 | } else { 111 | await this.installWinGet(); 112 | } 113 | } catch (error) { 114 | // await this.installWinGet(); 115 | // await this.startUp(); 116 | console.log("checkWinget error", error); 117 | } finally { 118 | this.loading = false; 119 | } 120 | } 121 | 122 | isInstalled(_package: any) { 123 | return this.installed.find((p: any) => p[0] === _package[0]); 124 | } 125 | 126 | doSearch() { 127 | setTimeout(() => { 128 | this.currentSearch = this.search; 129 | this.cdr.detectChanges(); 130 | }, 50); 131 | } 132 | 133 | async installWinGet() { 134 | return new Promise(async (resolve, reject) => { 135 | const data: any = await this.http 136 | .get("https://api.github.com/repos/microsoft/winget-cli/releases") 137 | .toPromise(); 138 | 139 | const latest = data[0]; 140 | const asset: any = latest.assets.find((asset: any) => 141 | asset.name.endsWith(".appxbundle") 142 | ); 143 | 144 | try { 145 | const tmp = ""; //this.electronService.app.getPath("temp"); 146 | 147 | await this.powershell( 148 | `Invoke-WebRequest -Uri ${asset.browser_download_url} -OutFile ${tmp}\\winget.appxbundle` 149 | ); 150 | await this.powershell( 151 | `Add-AppxPackage -Path "${tmp}\\winget.appxbundle"` 152 | ); 153 | resolve(true); 154 | } catch (error) { 155 | reject(error); 156 | } 157 | }); 158 | } 159 | 160 | async loadPackages() { 161 | this.packages = []; 162 | 163 | try { 164 | let result: any = await this.powershell( 165 | "winget search -q= --accept-source-agreements" 166 | ); 167 | result = result.split("----------------------------------").pop(); 168 | result = result 169 | .split("\n") 170 | .map((lines: any) => { 171 | lines = lines 172 | .replace(/ +(?= )/g, "\t") 173 | .split("\t") 174 | .map((line: any) => line.trim()); 175 | return lines; 176 | }) 177 | .slice(1); 178 | 179 | console.log("result", result); 180 | const installed = await this.loadInstalled(); 181 | // sort result by installed packages 182 | result = result.sort((a: any, b: any) => { 183 | const aInstalled = installed.find((p: any) => p[0] === a[0]); 184 | const bInstalled = installed.find((p: any) => p[0] === b[0]); 185 | if (aInstalled && !bInstalled) { 186 | return -1; 187 | } else if (!aInstalled && bInstalled) { 188 | return 1; 189 | } else { 190 | return 0; 191 | } 192 | }); 193 | 194 | this.packages = result; 195 | } catch (error) { 196 | } finally { 197 | } 198 | } 199 | 200 | async loadInstalled() { 201 | this.installed = []; 202 | 203 | try { 204 | let result: any = await this.powershell("winget list"); 205 | result = result.split("----------------------------------").pop(); 206 | result = result 207 | .split("\n") 208 | .map((lines: any) => { 209 | lines = lines 210 | .replace(/ +(?= )/g, "\t") 211 | .split("\t") 212 | .map((line: any) => line.trim()); 213 | return lines; 214 | }) 215 | .slice(1); 216 | 217 | console.log("loadInstalled", result); 218 | 219 | this.installed = result; 220 | return result; 221 | } catch (error) { 222 | } finally { 223 | } 224 | } 225 | 226 | async install(_package: any) { 227 | _package.loading = true; 228 | try { 229 | await this.powershell(`winget install ${_package[1]}`); 230 | this.installed.push(_package); 231 | this.toast.success("Package installed"); 232 | } catch (err) { 233 | this.toast.error("Package not installed"); 234 | } finally { 235 | _package.loading = false; 236 | } 237 | } 238 | 239 | async upgrade(_package: any) { 240 | console.log("uninstall", _package); 241 | _package.loading = true; 242 | try { 243 | await this.powershell(`winget upgrade --id ${_package[1]}`); 244 | } catch (err) { 245 | this.toast.error("Package not updated"); 246 | } finally { 247 | this.toast.success("Package updated"); 248 | _package.loading = false; 249 | } 250 | } 251 | 252 | async uninstall(_package: any) { 253 | console.log("uninstall", _package); 254 | _package.loading = true; 255 | try { 256 | await this.powershell(`winget uninstall ${_package[1]}`); 257 | this.installed = this.installed.filter((p: any) => p[0] !== _package[0]); 258 | } catch (err) { 259 | this.toast.error("Package not uninstalled"); 260 | } finally { 261 | this.toast.success("Package uninstalled"); 262 | _package.loading = false; 263 | } 264 | } 265 | 266 | async upgradeAll() { 267 | try { 268 | await this.powershell(`winget upgrade --all`); 269 | } catch (err) { 270 | } finally { 271 | } 272 | } 273 | 274 | async powershell(script: string) { 275 | const { stdout, stderr } = await new Command( 276 | "powershell", 277 | ["-exec", "bypass", script], 278 | { 279 | encoding: "utf-8", 280 | } 281 | ).execute(); 282 | console.log("stdout", stdout); 283 | return stdout; 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /src/assets/angular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/assets/tauri.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tauri + Angular 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from "@angular/core"; 2 | import { bootstrapApplication } from "@angular/platform-browser"; 3 | import { AppComponent } from "./app/app.component"; 4 | 5 | import { environment } from "./environments/environment"; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | bootstrapApplication(AppComponent).catch((err) => console.error(err)); 12 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import "zone.js"; // Included with Angular CLI. 49 | 50 | /*************************************************************************************************** 51 | * APPLICATION IMPORTS 52 | */ 53 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body, 7 | :root { 8 | @apply bg-slate-200; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | html, 13 | body, 14 | :root { 15 | @apply bg-slate-900; 16 | } 17 | } 18 | 19 | @keyframes hotToastEnterAnimationNegative { 20 | 0% { 21 | opacity: 0.5; 22 | transform: translate3d(0, -80px, 0) scale(0.6); 23 | } 24 | 25 | 100% { 26 | opacity: 1; 27 | transform: translate3d(0, 0, 0) scale(1); 28 | } 29 | } 30 | 31 | @keyframes hotToastEnterAnimationPositive { 32 | 0% { 33 | opacity: 0.5; 34 | transform: translate3d(0, 80px, 0) scale(0.6); 35 | } 36 | 37 | 100% { 38 | opacity: 1; 39 | transform: translate3d(0, 0, 0) scale(1); 40 | } 41 | } 42 | 43 | @keyframes hotToastExitAnimationPositive { 44 | 0% { 45 | opacity: 1; 46 | transform: translate3d(0, 0, -1px) scale(1); 47 | } 48 | 49 | 100% { 50 | opacity: 0; 51 | transform: translate3d(0, 130px, -1px) scale(0.5); 52 | } 53 | } 54 | 55 | @keyframes hotToastExitAnimationNegative { 56 | 0% { 57 | opacity: 1; 58 | transform: translate3d(0, 0, -1px) scale(1); 59 | } 60 | 61 | 100% { 62 | opacity: 0; 63 | transform: translate3d(0, -130px, -1px) scale(0.5); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /stuff/icon.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/stuff/icon.sketch -------------------------------------------------------------------------------- /stuff/logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codextde/winget-gui/4e356934e8c291bac492012c5b03a5044d4b7149/stuff/logo.psd -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{html,ts}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("daisyui")], 8 | }; 9 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": ["src/main.ts", "src/polyfills.ts"], 9 | "include": ["src/**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "es2020", 21 | "lib": [ 22 | "es2020", 23 | "dom" 24 | ], 25 | "useDefineForClassFields": false 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | --------------------------------------------------------------------------------