From 827e17dc6d99706e2c99204f88d2a5e73fb8d27e Mon Sep 17 00:00:00 2001 From: Vignesh Sankar Iyer <68676914+vigneshsankariyer1234567890@users.noreply.github.com> Date: Thu, 16 Mar 2023 14:01:23 +0800 Subject: [PATCH] Remove electron dependencies (#1153) Refactor and remove uses of Electron from CATcher There are many uses of Electron in CATcher, even with the CATcher Electron app being deprecated. As such, there are many instances of unused code, which is bad practice. Removing instances of uses of Electron allows us to trim the codebase and remove dead code. Let's * Refactor and remove uses of Electron from CATcher * Remove all uses of Electron in the `src` folder first. * Remove uses of Electron from `package.json` and other files * Delete folders such as `electron-utils` and files such as `postinstall` that are used to initialise electron * Remove and amend scripts in `package.json` that are involved in building the electron app * Edit `deployment-actions.yml` to remove pre-build actions from CD workflow --- .github/workflows/deployment-actions.yml | 81 ----------- .gitignore | 1 - electron-builder.json | 35 ----- electron-utils/menu-bar.ts | 73 ---------- electron-utils/oauth.ts | 128 ------------------ electron-utils/supporting-logic.ts | 25 ---- main.ts | 127 ----------------- package.json | 24 +--- postinstall-web.js | 16 --- postinstall.js | 16 --- src/app/app.component.ts | 30 +--- src/app/app.module.ts | 19 +-- src/app/auth/auth.component.ts | 18 +-- .../confirm-login.component.html | 5 +- .../confirm-login/confirm-login.component.ts | 3 - src/app/core/services/auth.service.ts | 20 +-- src/app/core/services/electron.service.ts | 64 --------- .../factories/factory.auth.service.ts | 3 - .../factories/factory.github.service.ts | 5 +- .../factories/factory.issue.service.ts | 4 +- src/app/core/services/github.service.ts | 10 +- src/app/core/services/issue.service.ts | 4 +- src/app/core/services/logging.service.ts | 12 +- src/app/shared/layout/header.component.ts | 6 +- .../issue-dispute/issue-dispute.component.ts | 6 +- .../issues-faulty.component.spec.ts | 2 +- .../issues-pending.component.spec.ts | 2 +- .../issues-responded.component.spec.ts | 2 +- .../shared/issue-tables/search-filter.spec.ts | 2 +- tests/services/logging.service.spec.ts | 4 +- tests/services/profile.service.spec.ts | 2 +- 31 files changed, 37 insertions(+), 712 deletions(-) delete mode 100644 electron-builder.json delete mode 100644 electron-utils/menu-bar.ts delete mode 100644 electron-utils/oauth.ts delete mode 100644 electron-utils/supporting-logic.ts delete mode 100644 main.ts delete mode 100644 postinstall-web.js delete mode 100644 postinstall.js delete mode 100644 src/app/core/services/electron.service.ts diff --git a/.github/workflows/deployment-actions.yml b/.github/workflows/deployment-actions.yml index 9ba4d9a4..94065894 100644 --- a/.github/workflows/deployment-actions.yml +++ b/.github/workflows/deployment-actions.yml @@ -56,84 +56,3 @@ jobs: - name: Set upload_url Context id: set_upload_url run: echo "::set-output name=upload_url::${{ steps.draft_release.outputs.upload_url }}" - - deploy_linux: - runs-on: ubuntu-latest - needs: draft_release - strategy: - matrix: - node-version: [14.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: Build - run: | - npm install - npm run electron:linux - - name: Upload Release Asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.draft_release.outputs.upload_url }} - asset_path: ./release/CATcher-${{ needs.draft_release.outputs.version_num }}.AppImage - asset_name: CATcher-${{ needs.draft_release.outputs.version_num }}.AppImage - asset_content_type: application/octet-stream - - deploy_windows: - runs-on: windows-latest - needs: draft_release - strategy: - matrix: - node-version: [14.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: Build - run: | - npm install - npm run electron:windows - - name: Upload Release Asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.draft_release.outputs.upload_url }} - asset_path: ./release/CATcher ${{ needs.draft_release.outputs.version_num }}.exe - asset_name: CATcher-${{ needs.draft_release.outputs.version_num }}.exe - asset_content_type: application/octet-stream - - deploy_macos: - runs-on: macos-latest - needs: draft_release - strategy: - matrix: - node-version: [14.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: Build - run: | - npm install - npm run electron:mac - - name: Upload Release Asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.draft_release.outputs.upload_url }} - asset_path: ./release/CATcher-${{ needs.draft_release.outputs.version_num }}.dmg - asset_name: CATcher-${{ needs.draft_release.outputs.version_num }}.dmg - asset_content_type: application/octet-stream diff --git a/.gitignore b/.gitignore index 1b43aed9..1ed2c828 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ /release main.js src/**/*.js -electron-utils/*.js *.js.map # tests coverage diff --git a/electron-builder.json b/electron-builder.json deleted file mode 100644 index 38700ac2..00000000 --- a/electron-builder.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "appId": "CATcher", - "productName": "CATcher", - "directories": { - "output": "release/" - }, - "files": [ - "**/*", - "!**/*.ts", - "!*.code-workspace", - "!LICENSE.md", - "!package.json", - "!package-lock.json", - "!src/", - "!e2e/", - "!hooks/", - "!angular.json", - "!_config.yml", - "!karma.conf.js", - "!tsconfig.json", - "!tslint.json" - ], - "win": { - "icon": "dist/favicon.png", - "target": ["portable"] - }, - "mac": { - "icon": "dist/favicon.png", - "target": ["dmg"] - }, - "linux": { - "icon": "dist/favicon.png", - "target": ["AppImage"] - } -} diff --git a/electron-utils/menu-bar.ts b/electron-utils/menu-bar.ts deleted file mode 100644 index 03965cad..00000000 --- a/electron-utils/menu-bar.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { app, BrowserWindow, Menu, MenuItem, MenuItemConstructorOptions } from 'electron'; - -// Edited version of a template menu-bar provided by the electron API, -// refer to https://electronjs.org/docs/api/menu for more information. -const fileMenu: MenuItemConstructorOptions = { - label: 'File', - submenu: [ - { - label: 'Quit CATcher', - accelerator: 'CmdOrCtrl+Q', - click() { - app.quit(); - } - } - ] -}; - -const editMenu: MenuItemConstructorOptions = { - label: 'Edit', - submenu: [ - { role: 'undo' }, - { role: 'redo' }, - { type: 'separator' }, - { role: 'selectAll' }, - { role: 'cut' }, - { role: 'copy' }, - { role: 'paste' }, - { role: 'delete' } - ] -}; - -const viewMenu: MenuItemConstructorOptions = { - label: 'View', - submenu: [{ role: 'resetZoom' }, { role: 'zoomIn' }, { role: 'zoomOut' }, { type: 'separator' }, { role: 'togglefullscreen' }] -}; - -export function createMenuOptions(isDevMode: boolean): MenuItemConstructorOptions[] { - const mainMenuTemplate: MenuItemConstructorOptions[] = [fileMenu, editMenu, viewMenu]; - - if (isDevMode) { - let viewSubMenu: MenuItemConstructorOptions[]; - viewSubMenu = mainMenuTemplate[2].submenu as MenuItemConstructorOptions[]; - viewSubMenu.push({ type: 'separator' }, { role: 'toggleDevTools' }); - } - return mainMenuTemplate; -} - -function createInspectElementMenuItem(contextMenuCoords: { x; y }): MenuItem { - return new MenuItem({ - label: 'Inspect Element', - click: (menuItem, window, event) => { - window.webContents.inspectElement(contextMenuCoords.x, contextMenuCoords.y); - } - }); -} - -/** - * Creates a menu that is displayed when the context-menu event fires on the - * given BrowserWindow (i.e. usually when user right-clicks on the window). - * This menu will contain an 'Inspect Element' MenuItem. - */ -export function createContextMenu(win: BrowserWindow): void { - const contextMenuCoords = { x: null, y: null }; - const contextMenu = new Menu(); - contextMenu.append(createInspectElementMenuItem(contextMenuCoords)); - - win.webContents.on('context-menu', (event, contextMenuParams) => { - // record the mouse position, when context-menu event is fired - contextMenuCoords.x = contextMenuParams.x; - contextMenuCoords.y = contextMenuParams.y; - contextMenu.popup({ window: win }); - }); -} diff --git a/electron-utils/oauth.ts b/electron-utils/oauth.ts deleted file mode 100644 index 0aea0337..00000000 --- a/electron-utils/oauth.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { BrowserWindow, shell } from 'electron'; -import { v4 as uuid } from 'uuid'; - -const nodeUrl = require('url'); -const Logger = require('electron-log'); -const fetch = require('node-fetch'); - -const CLIENT_ID = '6750652c0c9001314434'; -const BASE_URL = 'https://github.com'; -const ACCESS_TOKEN_URL = 'https://catcher-auth.herokuapp.com/authenticate'; -const CALLBACK_URL = 'http://localhost:4200'; - -let authWindow; - -/** - * Will retrieve the access token from a proxy server which acts as a intermediary to retrieve the tokens from Github. - * @param window - The main window of CATcher. - * @param repoPermissionLevel - The level of permission required to be granted by the user to use CATcher. - */ -export function getAccessToken(window: BrowserWindow, repoPermissionLevel: string): Promise { - return getAuthorizationCode(window, repoPermissionLevel) - .then((code) => { - Logger.info('Obtained authorization code from Github'); - const accessTokenUrl = `${ACCESS_TOKEN_URL}/${code}`; - return fetch(accessTokenUrl) - .then((res) => res.json()) - .then((data: { error }) => { - if (data.error) { - throw new Error(data.error); - } - return data; - }); - }) - .catch((error) => { - throw error; - }); -} - -/** - * Get the authorization code from Github after success login. - * @param parentWindow - The main window of CATcher - * @param repoPermissionLevel - The level of permission required to be granted by the user to use CATcher. - */ -function getAuthorizationCode(parentWindow: BrowserWindow, repoPermissionLevel: string) { - let state: string; - state = generateStateString(); - const oauthUrl = encodeURI( - `${BASE_URL}/login/oauth/authorize?client_id=${CLIENT_ID}&scope=${repoPermissionLevel},read:user&state=${state}` - ); - - return new Promise(function (resolve, reject) { - const windowParams = { - autoHideMenuBar: true, - alwaysOnTop: false, - fullscreenable: false, - parent: parentWindow, - webPreferences: { - nodeIntegration: true - } - }; - authWindow = new BrowserWindow(windowParams); - authWindow.loadURL(oauthUrl); - authWindow.show(); - Logger.info('Opening authentication window'); - - authWindow.on('closed', (event) => { - reject(new Error('WINDOW_CLOSED')); - }); - - authWindow.webContents.on('will-navigate', (event, newUrl) => { - if (newUrl.startsWith(CALLBACK_URL)) { - onCallback(newUrl); - } else if (newUrl.startsWith(`${BASE_URL}/session`) || newUrl.startsWith(`${BASE_URL}/login`)) { - // continue navigation within the auth window - return; - } else { - // do not navigate to external links in the auth window - // instead, navigate to them in the user's browser - event.preventDefault(); - shell.openExternal(newUrl).then(() => Logger.info('External link is clicked on auth window, opening system browser...')); - } - }); - - authWindow.webContents.on('new-window', (event, url, frameName, disposition, options) => { - event.preventDefault(); - shell.openExternal(url).then(() => Logger.info('External link is clicked on auth window, opening system browser...')); - }); - - authWindow.webContents.on('will-redirect', (event, newUrl) => { - Logger.info('Received redirect in auth window'); - if (newUrl.startsWith(CALLBACK_URL)) { - onCallback(newUrl); - } - }); - - function onCallback(callbackUrl: string) { - const url_parts = nodeUrl.parse(callbackUrl, true); - const query = url_parts.query; - const code = query.code; - const error = query.error; - const returnedState = query.state; - - if (error !== undefined) { - reject(error); - } else if (isReturnedStateSame(state, returnedState) && code) { - resolve(code); - } - setImmediate(function () { - authWindow.close(); - authWindow.on('closed', () => { - Logger.info('Closing authentication window'); - authWindow = null; - }); - }); - } - }); -} - -/** - * Generates and assigns an unguessable random 'state' string to pass to Github for protection against cross-site request forgery attacks - */ -function generateStateString(): string { - return uuid(); -} - -function isReturnedStateSame(state: string, returnedState: string): boolean { - return state === returnedState; -} diff --git a/electron-utils/supporting-logic.ts b/electron-utils/supporting-logic.ts deleted file mode 100644 index 6e6f522d..00000000 --- a/electron-utils/supporting-logic.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { app } from 'electron'; - -export function isDeveloperMode(): boolean { - const args = process.argv.slice(1), - serve = args.some((val) => val === '--serve'); - return !!serve; -} - -export function isWindowsOs(): boolean { - return process.platform === 'win32'; -} - -export function isMacOs(): boolean { - return process.platform === 'darwin'; -} - -export function isLinuxOs(): boolean { - return process.platform === 'linux'; -} - -export function getCurrentDirectory(isWindowsOs: boolean, isDevMode: boolean): string { - return isWindowsOs ? (isDevMode ? app.getAppPath() : process.env.PORTABLE_EXECUTABLE_FILE) : app.getAppPath(); -} - -export const appTitle: string = require('../package.json').name + ' ' + require('../package.json').version; diff --git a/main.ts b/main.ts deleted file mode 100644 index 960b0200..00000000 --- a/main.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { app, BrowserWindow, ipcMain, Menu, MenuItemConstructorOptions, nativeTheme, screen, shell } from 'electron'; -import * as path from 'path'; -import * as url from 'url'; -import { createContextMenu, createMenuOptions } from './electron-utils/menu-bar'; -import { getAccessToken } from './electron-utils/oauth'; -import { appTitle, isDeveloperMode, isLinuxOs, isMacOs } from './electron-utils/supporting-logic'; - -const Logger = require('electron-log'); -const ICON_PATH = path.join(__dirname, 'dist/favicon.512x512.png'); - -let win: BrowserWindow = null; -const isDevMode = isDeveloperMode(); - -/** - * Will start the OAuth Web Flow and obtain the access token from Github. - */ -ipcMain.on('github-oauth', (event, repoPermissionLevel) => { - Logger.info('Starting authentication'); - getAccessToken(win, repoPermissionLevel) - .then((data) => { - Logger.info('Obtained access token from Github'); - event.sender.send('github-oauth-reply', { token: data.token }); - }) - .catch((error) => { - event.sender.send('github-oauth-reply', { - error: error.message, - isWindowClosed: error.message === 'WINDOW_CLOSED' - }); - }); -}); - -ipcMain.handle('clear-storage', () => { - return win.webContents.session.clearStorageData(); -}); - -ipcMain.handle('open-link', (e, address) => { - shell.openExternal(address); -}); - -function createWindow() { - Logger.info('Creating primary window.'); - const size = screen.getPrimaryDisplay().workAreaSize; - const windowOptions = { - x: 0, - y: 0, - width: size.width, - height: size.height, - webPreferences: { - nodeIntegration: true, - allowRunningInsecureContent: !isDevMode - } - }; - - if (isLinuxOs()) { - // app icon needs to be set manually on Linux platforms - windowOptions['icon'] = ICON_PATH; - } - - // Create the browser window. - win = new BrowserWindow(windowOptions); - win.setTitle(appTitle); - - nativeTheme.themeSource = 'light'; - - if (isDevMode) { - require('electron-reload')(__dirname, { - electron: require(`${__dirname}/node_modules/electron`) - }); - - createContextMenu(win); - win.loadURL('http://localhost:4200'); - win.webContents.openDevTools(); - } else { - win.loadURL( - url.format({ - pathname: path.join(__dirname, 'dist/index.html'), - protocol: 'file:', - slashes: true - }) - ); - } - - // Emitted when the window is closed. - win.on('closed', () => { - // Dereference the window object, usually you would store window - // in an array if your app supports multi windows, this is the time - // when you should delete the corresponding element. - win = null; - }); -} - -try { - Logger.info('Initializing Electron app.'); - // This method will be called when Electron has finished - // initialization and is ready to create browser windows. - // Some APIs can only be used after this event occurs. - app.on('ready', () => { - Logger.info('Electron app in ready state.'); - // Build and Attach Menu-bar template to application. - const mainMenuTemplate: MenuItemConstructorOptions[] = createMenuOptions(isDevMode); - const mainMenu = Menu.buildFromTemplate(mainMenuTemplate); - Menu.setApplicationMenu(mainMenu); - - createWindow(); - }); - - // Quit when all windows are closed. - app.on('window-all-closed', () => { - Logger.info('Closing all windows in Electron.'); - // On OS X it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q - if (!isMacOs()) { - app.quit(); - } - }); - - app.on('activate', () => { - Logger.info('Electron app is activated.'); - // On OS X it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (win === null) { - createWindow(); - } - }); -} catch (e) { - Logger.error('Something went wrong in Electron.', e); -} diff --git a/package.json b/package.json index e0c13a3e..5869f342 100644 --- a/package.json +++ b/package.json @@ -3,29 +3,17 @@ "version": "3.4.6", "main": "main.js", "scripts": { - "postinstall": "npm run postinstall:electron && electron-builder install-app-deps", - "postinstall:electron": "node postinstall", - "postinstall:web": "node postinstall-web", "ng": "ng", - "start": "npm run postinstall:electron && npm-run-all -p codegen:gql-watch ng:serve electron:serve", - "build": "npm run postinstall:electron && npm run codegen:gql && npm run electron:serve-tsc && ng build", - "build:prod": "npm run build -- -c production --base-href=./", "build:staging": "npm run codegen:gql && ng build --c staging --base-href=https://catcher-org.github.io/CATcher-staging/", "build:prod:web": "npm run codegen:gql && ng build --prod --base-href=https://CATcher-org.github.io/CATcher/", "ng:serve": "npm run codegen:gql && ng serve", - "ng:serve:web": "npm run postinstall:web && npm run ng:serve -- -o", + "ng:serve:web": "npm run ng:serve -- -o", "deploy:staging": "npm run build:staging && ngh --dir=dist --name=CATcher --email=se-edu@comp.nus.edu.sg --no-silent", - "ng:serve:test": "npm run postinstall:web && npm run ng:serve -- --configuration=test -o", + "ng:serve:test": "npm run ng:serve -- --configuration=test -o", "deploy:web": "npm run build:prod:web && ngh --dir=dist --name=CATcher --email=se-edu@comp.nus.edu.sg --no-silent", - "electron:serve-tsc": "tsc -p tsconfig-serve.json", - "electron:serve": "wait-on http-get://localhost:4200/ && npm run electron:serve-tsc && electron . --serve", - "electron:local": "npm run build:prod && electron .", - "electron:linux": "npm run build:prod && electron-builder build --linux --publish never", - "electron:windows": "npm run build:prod && electron-builder build --windows --publish never", - "electron:mac": "npm run build:prod && electron-builder build --mac --publish never", "test": "npm run codegen:gql && ng test", - "e2e": "npm run codegen:gql && npm run postinstall:web && ng e2e", - "actions:e2e": "npm run codegen:gql && npm run postinstall:web && ng e2e --protractor-config=e2e/protractor.gh-actions.conf --webdriver-update=false", + "e2e": "npm run codegen:gql && ng e2e", + "actions:e2e": "npm run codegen:gql && ng e2e --protractor-config=e2e/protractor.gh-actions.conf --webdriver-update=false", "webdriver-manager": "webdriver-manager", "lint": "ng lint", "lint:fix": "ng lint --fix", @@ -64,7 +52,6 @@ "core-js": "^3.16.4", "diff-match-patch": "^1.0.4", "dompurify": "^2.3.1", - "electron-log": "^4.4.1", "graphql": "^14.6.0", "graphql-tag": "2.11.0", "karma-spec-reporter": "0.0.32", @@ -94,9 +81,6 @@ "@types/node": "^15.6.1", "angular-cli-ghpages": "^1.0.0-rc.2", "codelyzer": "^5.1.2", - "electron": "11.4.8", - "electron-builder": "22.2.0", - "electron-reload": "1.5.0", "graphql-codegen-fragment-matcher": "^0.18.2", "husky": "^4.2.5", "jasmine": "^3.9.0", diff --git a/postinstall-web.js b/postinstall-web.js deleted file mode 100644 index 7dce7645..00000000 --- a/postinstall-web.js +++ /dev/null @@ -1,16 +0,0 @@ -// Allow angular using electron module (native node modules) -const fs = require('fs'); -const f_angular = 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js'; - -fs.readFile(f_angular, 'utf8', function (err, data) { - if (err) { - return console.log(err); - } - var result = data.replace(/target: "electron-renderer",/g, ''); - var result = result.replace(/target: "web",/g, ''); - var result = result.replace(/return \{/g, 'return {target: "web",'); - - fs.writeFile(f_angular, result, 'utf8', function (err) { - if (err) return console.log(err); - }); -}); \ No newline at end of file diff --git a/postinstall.js b/postinstall.js deleted file mode 100644 index 1fb12759..00000000 --- a/postinstall.js +++ /dev/null @@ -1,16 +0,0 @@ -// Allow angular using electron module (native node modules) -const fs = require('fs'); -const f_angular = 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js'; - -fs.readFile(f_angular, 'utf8', function (err, data) { - if (err) { - return console.log(err); - } - var result = data.replace(/target: "electron-renderer",/g, ''); - var result = result.replace(/target: "web",/g, ''); - var result = result.replace(/return \{/g, 'return {target: "electron-renderer",'); - - fs.writeFile(f_angular, result, 'utf8', function (err) { - if (err) return console.log(err); - }); -}); \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 42419f9b..243f3be7 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,6 +1,5 @@ import { AfterViewInit, Component } from '@angular/core'; import { AppConfig } from '../environments/environment'; -import { ElectronService } from './core/services/electron.service'; import { ErrorHandlingService } from './core/services/error-handling.service'; import { LoggingService } from './core/services/logging.service'; @@ -12,40 +11,15 @@ import { LoggingService } from './core/services/logging.service'; export class AppComponent implements AfterViewInit { NOT_CONNECTED_ERROR: Error = new Error('You are not connected to the internet.'); - constructor(public electronService: ElectronService, logger: LoggingService, public errorHandlingService: ErrorHandlingService) { + constructor(logger: LoggingService, public errorHandlingService: ErrorHandlingService) { logger.info('AppComponent: AppConfig', AppConfig); - - if (electronService.isElectron()) { - logger.info('AppComponent: Mode electron'); - } else { - logger.info('AppComponent: Mode web'); - } + logger.info('AppComponent: Mode web'); } ngAfterViewInit() { - this.addListenerForHttpLinks(); this.addListenerForNetworkOffline(); } - /** - * This listener will prevent the default behaviour of electron to open http links on electron browser itself. - * Will use the client's default OS browser to open the link. - */ - addListenerForHttpLinks() { - document.addEventListener( - 'click', - (event) => { - const elem = (event.target).closest('a[href^="http"]'); - if (elem) { - event.preventDefault(); - event.stopPropagation(); - this.electronService.openLink(elem.href); - } - }, - false - ); - } - /** * This listener checks if CATcher has a connection to a network, and will show an error snackbar if it does not. */ diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b86441cc..ba6f9506 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -18,7 +18,6 @@ import { AuthModule } from './auth/auth.module'; import { UserConfirmationComponent } from './core/guards/user-confirmation/user-confirmation.component'; import { AuthService } from './core/services/auth.service'; import { DataService } from './core/services/data.service'; -import { ElectronService } from './core/services/electron.service'; import { ErrorHandlingService } from './core/services/error-handling.service'; import { AuthServiceFactory } from './core/services/factories/factory.auth.service'; import { GithubServiceFactory } from './core/services/factories/factory.github.service'; @@ -65,29 +64,17 @@ import { SharedModule } from './shared/shared.module'; { provide: GithubService, useFactory: GithubServiceFactory, - deps: [ErrorHandlingService, Apollo, ElectronService, LoggingService] + deps: [ErrorHandlingService, Apollo, LoggingService] }, { provide: AuthService, useFactory: AuthServiceFactory, - deps: [ - ElectronService, - Router, - NgZone, - GithubService, - UserService, - IssueService, - PhaseService, - DataService, - GithubEventService, - Title, - LoggingService - ] + deps: [Router, NgZone, GithubService, UserService, IssueService, PhaseService, DataService, GithubEventService, Title, LoggingService] }, { provide: IssueService, useFactory: IssueServiceFactory, - deps: [GithubService, UserService, PhaseService, ElectronService, DataService, LoggingService] + deps: [GithubService, UserService, PhaseService, DataService, LoggingService] }, { provide: ErrorHandler, diff --git a/src/app/auth/auth.component.ts b/src/app/auth/auth.component.ts index 5195127d..c77aab43 100644 --- a/src/app/auth/auth.component.ts +++ b/src/app/auth/auth.component.ts @@ -6,7 +6,6 @@ import { AppConfig } from '../../environments/environment'; import { GithubUser } from '../core/models/github-user.model'; import { ApplicationService } from '../core/services/application.service'; import { AuthService, AuthState } from '../core/services/auth.service'; -import { ElectronService } from '../core/services/electron.service'; import { ErrorHandlingService } from '../core/services/error-handling.service'; import { GithubService } from '../core/services/github.service'; import { LoggingService } from '../core/services/logging.service'; @@ -30,7 +29,6 @@ export class AuthComponent implements OnInit, OnDestroy { constructor( public appService: ApplicationService, - public electronService: ElectronService, private githubService: GithubService, private authService: AuthService, private userService: UserService, @@ -40,20 +38,7 @@ export class AuthComponent implements OnInit, OnDestroy { private ngZone: NgZone, private activatedRoute: ActivatedRoute, private logger: LoggingService - ) { - this.electronService.registerIpcListener('github-oauth-reply', (event, { token, error, isWindowClosed }) => { - this.ngZone.run(() => { - if (error) { - if (!isWindowClosed) { - this.errorHandlingService.handleError(error); - } - this.goToSessionSelect(); - return; - } - this.authService.storeOAuthAccessToken(token); - }); - }); - } + ) {} ngOnInit() { this.logger.startSession(); @@ -108,7 +93,6 @@ export class AuthComponent implements OnInit, OnDestroy { } ngOnDestroy() { - this.electronService.removeIpcListeners('github-oauth-reply'); if (this.authStateSubscription) { this.authStateSubscription.unsubscribe(); } diff --git a/src/app/auth/confirm-login/confirm-login.component.html b/src/app/auth/confirm-login/confirm-login.component.html index de429fef..38d2a365 100644 --- a/src/app/auth/confirm-login/confirm-login.component.html +++ b/src/app/auth/confirm-login/confirm-login.component.html @@ -3,10 +3,7 @@ Continue as {{ this.username }} - -
+
To change account, please sign into the desired account from the official Github website.
diff --git a/src/app/auth/confirm-login/confirm-login.component.ts b/src/app/auth/confirm-login/confirm-login.component.ts index 71011d0c..e292672a 100644 --- a/src/app/auth/confirm-login/confirm-login.component.ts +++ b/src/app/auth/confirm-login/confirm-login.component.ts @@ -2,7 +2,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { mergeMap } from 'rxjs/operators'; import { AuthService, AuthState } from '../../core/services/auth.service'; -import { ElectronService } from '../../core/services/electron.service'; import { ErrorHandlingService } from '../../core/services/error-handling.service'; import { GithubEventService } from '../../core/services/githubevent.service'; import { LoggingService } from '../../core/services/logging.service'; @@ -19,7 +18,6 @@ export class ConfirmLoginComponent implements OnInit { @Input() currentSessionOrg: string; constructor( - public electronService: ElectronService, private authService: AuthService, private phaseService: PhaseService, private userService: UserService, @@ -38,7 +36,6 @@ export class ConfirmLoginComponent implements OnInit { logIntoAnotherAccount() { this.logger.info('ConfirmLoginComponent: Logging into another account'); - this.electronService.clearCookies(); this.authService.startOAuthProcess(); } diff --git a/src/app/core/services/auth.service.ts b/src/app/core/services/auth.service.ts index 730236e9..cf8a9cb6 100644 --- a/src/app/core/services/auth.service.ts +++ b/src/app/core/services/auth.service.ts @@ -7,7 +7,6 @@ import { AppConfig } from '../../../environments/environment'; import { generateSessionId } from '../../shared/lib/session'; import { uuid } from '../../shared/lib/uuid'; import { DataService } from './data.service'; -import { ElectronService } from './electron.service'; import { GithubService } from './github.service'; import { GithubEventService } from './githubevent.service'; import { IssueService } from './issue.service'; @@ -39,7 +38,6 @@ export class AuthService { ENABLE_POPUP_MESSAGE = 'Please enable pop-ups in your browser'; constructor( - private electronService: ElectronService, private router: Router, private ngZone: NgZone, private githubService: GithubService, @@ -128,17 +126,13 @@ export class AuthService { const githubRepoPermission = this.phaseService.githubRepoPermissionLevel(); this.changeAuthState(AuthState.AwaitingAuthentication); - if (this.electronService.isElectron()) { - this.electronService.sendIpcMessage('github-oauth', githubRepoPermission); - } else { - this.generateStateString(); - this.redirectToOAuthPage( - encodeURI( - `${AppConfig.githubUrl}/login/oauth/authorize?client_id=${AppConfig.clientId}&scope=${githubRepoPermission},read:user&state=${this.state}` - ) - ); - this.logger.info('AuthService: Redirecting for Github authentication'); - } + this.generateStateString(); + this.redirectToOAuthPage( + encodeURI( + `${AppConfig.githubUrl}/login/oauth/authorize?client_id=${AppConfig.clientId}&scope=${githubRepoPermission},read:user&state=${this.state}` + ) + ); + this.logger.info('AuthService: Redirecting for Github authentication'); } /** diff --git a/src/app/core/services/electron.service.ts b/src/app/core/services/electron.service.ts deleted file mode 100644 index 53ebc931..00000000 --- a/src/app/core/services/electron.service.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Injectable } from '@angular/core'; -import { ipcRenderer } from 'electron'; - -declare var window: Window; -declare global { - interface Window { - process: any; - require: any; - } -} - -@Injectable({ - providedIn: 'root' -}) - -/** - * Responsible for setting up the electron application environment and the - * respective event listeners and handlers. - */ -export class ElectronService { - ipcRenderer: typeof ipcRenderer; - - constructor() { - if (this.isElectron()) { - this.ipcRenderer = window.require('electron').ipcRenderer; - } - } - - isElectron(): boolean { - return window && window.process && window.process.type; - } - - clearCookies() { - if (this.isElectron()) { - this.ipcRenderer.invoke('clear-storage'); - } - } - - registerIpcListener(channel: string, callback: (...params) => void) { - if (this.isElectron()) { - this.ipcRenderer.on(channel, callback); - } - } - - sendIpcMessage(channel: string, ...messages: any) { - if (this.isElectron()) { - this.ipcRenderer.send(channel, messages); - } - } - - removeIpcListeners(channel: string) { - if (this.isElectron()) { - this.ipcRenderer.removeAllListeners(channel); - } - } - - openLink(address: string) { - if (this.isElectron()) { - this.ipcRenderer.invoke('open-link', address); - } else { - window.open(address); - } - } -} diff --git a/src/app/core/services/factories/factory.auth.service.ts b/src/app/core/services/factories/factory.auth.service.ts index 3fc70ff8..0b287ce4 100644 --- a/src/app/core/services/factories/factory.auth.service.ts +++ b/src/app/core/services/factories/factory.auth.service.ts @@ -4,7 +4,6 @@ import { Router } from '@angular/router'; import { AppConfig } from '../../../../environments/environment'; import { AuthService } from '../auth.service'; import { DataService } from '../data.service'; -import { ElectronService } from '../electron.service'; import { GithubService } from '../github.service'; import { GithubEventService } from '../githubevent.service'; import { IssueService } from '../issue.service'; @@ -14,7 +13,6 @@ import { PhaseService } from '../phase.service'; import { UserService } from '../user.service'; export function AuthServiceFactory( - electronService: ElectronService, router: Router, ngZone: NgZone, githubService: GithubService, @@ -42,7 +40,6 @@ export function AuthServiceFactory( } console.log(logger); return new AuthService( - electronService, router, ngZone, githubService, diff --git a/src/app/core/services/factories/factory.github.service.ts b/src/app/core/services/factories/factory.github.service.ts index ecfba3be..9a199a9d 100644 --- a/src/app/core/services/factories/factory.github.service.ts +++ b/src/app/core/services/factories/factory.github.service.ts @@ -1,14 +1,13 @@ import { Apollo } from 'apollo-angular'; import { AppConfig } from '../../../../environments/environment'; -import { ElectronService } from '../electron.service'; import { ErrorHandlingService } from '../error-handling.service'; import { GithubService } from '../github.service'; import { LoggingService } from '../logging.service'; import { MockGithubService } from '../mocks/mock.github.service'; -export function GithubServiceFactory(handling: ErrorHandlingService, apollo: Apollo, electron: ElectronService, logger: LoggingService) { +export function GithubServiceFactory(handling: ErrorHandlingService, apollo: Apollo, logger: LoggingService) { if (AppConfig.test) { return new MockGithubService(); } - return new GithubService(handling, apollo, electron, logger); + return new GithubService(handling, apollo, logger); } diff --git a/src/app/core/services/factories/factory.issue.service.ts b/src/app/core/services/factories/factory.issue.service.ts index ea67a227..12c744da 100644 --- a/src/app/core/services/factories/factory.issue.service.ts +++ b/src/app/core/services/factories/factory.issue.service.ts @@ -1,6 +1,5 @@ import { AppConfig } from '../../../../environments/environment'; import { DataService } from '../data.service'; -import { ElectronService } from '../electron.service'; import { GithubService } from '../github.service'; import { IssueService } from '../issue.service'; import { LoggingService } from '../logging.service'; @@ -12,12 +11,11 @@ export function IssueServiceFactory( githubService: GithubService, userService: UserService, phaseService: PhaseService, - electronService: ElectronService, dataService: DataService, logger: LoggingService ) { if (AppConfig.test) { return new MockIssueService(githubService, phaseService, dataService); } - return new IssueService(githubService, userService, phaseService, electronService, dataService, logger); + return new IssueService(githubService, userService, phaseService, dataService, logger); } diff --git a/src/app/core/services/github.service.ts b/src/app/core/services/github.service.ts index 76167fdf..db45956f 100644 --- a/src/app/core/services/github.service.ts +++ b/src/app/core/services/github.service.ts @@ -29,7 +29,6 @@ import { GithubLabel } from '../models/github/github-label.model'; import { GithubResponse } from '../models/github/github-response.model'; import { GithubRelease } from '../models/github/github.release'; import { SessionData } from '../models/session.model'; -import { ElectronService } from './electron.service'; import { ERRORCODE_NOT_FOUND, ErrorHandlingService } from './error-handling.service'; import { LoggingService } from './logging.service'; @@ -62,12 +61,7 @@ export class GithubService { private issuesLastModifiedManager = new IssueLastModifiedManagerModel(); private issueQueryRefs = new Map>(); - constructor( - private errorHandlingService: ErrorHandlingService, - private apollo: Apollo, - private electronService: ElectronService, - private logger: LoggingService - ) {} + constructor(private errorHandlingService: ErrorHandlingService, private apollo: Apollo, private logger: LoggingService) {} storeOAuthAccessToken(accessToken: string) { octokit = new Octokit({ @@ -427,7 +421,7 @@ export class GithubService { viewIssueInBrowser(id: number, event: Event) { if (id) { - this.electronService.openLink('https://github.com/'.concat(this.getRepoURL()).concat('/issues/').concat(String(id))); + window.open('https://github.com/'.concat(this.getRepoURL()).concat('/issues/').concat(String(id))); } else { this.errorHandlingService.handleError(new Error(UNABLE_TO_OPEN_IN_BROWSER)); } diff --git a/src/app/core/services/issue.service.ts b/src/app/core/services/issue.service.ts index 26a81a15..5b55cab1 100644 --- a/src/app/core/services/issue.service.ts +++ b/src/app/core/services/issue.service.ts @@ -12,7 +12,6 @@ import { FILTER, Issue, Issues, IssuesFilter, STATUS } from '../models/issue.mod import { Phase } from '../models/phase.model'; import { appVersion } from './application.service'; import { DataService } from './data.service'; -import { ElectronService } from './electron.service'; import { GithubService } from './github.service'; import { LoggingService } from './logging.service'; import { PhaseService } from './phase.service'; @@ -42,7 +41,6 @@ export class IssueService { private githubService: GithubService, private userService: UserService, private phaseService: PhaseService, - private electronService: ElectronService, private dataService: DataService, private logger: LoggingService ) { @@ -125,7 +123,7 @@ export class IssueService { createIssue(title: string, description: string, severity: string, type: string): Observable { const labelsArray = [this.createLabel('severity', severity), this.createLabel('type', type)]; - const clientType = this.electronService.isElectron() ? 'Desktop' : 'Web'; + const clientType = 'Desktop'; const hiddenData = new Map([ ['session', this.sessionId], ['Version', `${clientType} v${appVersion}`] diff --git a/src/app/core/services/logging.service.ts b/src/app/core/services/logging.service.ts index fbce78a4..94335da8 100644 --- a/src/app/core/services/logging.service.ts +++ b/src/app/core/services/logging.service.ts @@ -1,8 +1,6 @@ import { Injectable } from '@angular/core'; -import { ElectronLog } from 'electron-log'; import { AppConfig } from '../../../environments/environment'; import { downloadAsTextFile } from '../../shared/lib/file-download'; -import { ElectronService } from './electron.service'; @Injectable({ providedIn: 'root' @@ -13,7 +11,7 @@ import { ElectronService } from './electron.service'; * running to ease debugging for CATcher developers and maintainers. */ export class LoggingService { - private logger: ElectronLog | Console; + private logger: Console; private isInSession = false; private readonly LOG_KEY = 'CATcher-Log'; private readonly LOG_FILE_NAME = 'CATcher-log.txt'; @@ -21,12 +19,8 @@ export class LoggingService { public readonly LOG_COUNT_LIMIT = 4; public readonly SESSION_LOG_SEPARATOR = '\n'.repeat(2); // More new-lines added for clarity. - constructor(electronService: ElectronService) { - if (electronService.isElectron()) { - this.logger = window.require('electron-log'); - } else { - this.logger = console; - } + constructor() { + this.logger = console; this.startSession(); } diff --git a/src/app/shared/layout/header.component.ts b/src/app/shared/layout/header.component.ts index 376057fa..9f6588d0 100644 --- a/src/app/shared/layout/header.component.ts +++ b/src/app/shared/layout/header.component.ts @@ -7,7 +7,6 @@ import { Phase } from '../../core/models/phase.model'; import { UserRole } from '../../core/models/user.model'; import { AuthService } from '../../core/services/auth.service'; import { DialogService } from '../../core/services/dialog.service'; -import { ElectronService } from '../../core/services/electron.service'; import { ErrorHandlingService } from '../../core/services/error-handling.service'; import { GithubService } from '../../core/services/github.service'; import { GithubEventService } from '../../core/services/githubevent.service'; @@ -46,7 +45,6 @@ export class HeaderComponent implements OnInit { private issueService: IssueService, private errorHandlingService: ErrorHandlingService, private githubService: GithubService, - private electronService: ElectronService, private dialogService: DialogService ) { router.events @@ -134,11 +132,11 @@ export class HeaderComponent implements OnInit { issueUrl = routerUrl.substring(issueUrlIndex); } // Open the url in user's preferred browser - this.electronService.openLink('https://github.com/'.concat(this.githubService.getRepoURL()).concat(issueUrl)); + window.open('https://github.com/'.concat(this.githubService.getRepoURL()).concat(issueUrl)); } openIssueTracker() { - this.electronService.openLink(ISSUE_TRACKER_URL); + window.open(ISSUE_TRACKER_URL); } private getTeamFilterString() { diff --git a/src/app/shared/view-issue/issue-dispute/issue-dispute.component.ts b/src/app/shared/view-issue/issue-dispute/issue-dispute.component.ts index f9406a90..cca68164 100644 --- a/src/app/shared/view-issue/issue-dispute/issue-dispute.component.ts +++ b/src/app/shared/view-issue/issue-dispute/issue-dispute.component.ts @@ -4,7 +4,6 @@ import { Observable, throwError } from 'rxjs'; import { finalize, map, mergeMap } from 'rxjs/operators'; import { IssueComment } from '../../../core/models/comment.model'; import { Issue } from '../../../core/models/issue.model'; -import { ElectronService } from '../../../core/services/electron.service'; import { ErrorHandlingService } from '../../../core/services/error-handling.service'; import { GithubService } from '../../../core/services/github.service'; import { IssueService } from '../../../core/services/issue.service'; @@ -36,8 +35,7 @@ export class IssueDisputeComponent implements OnInit, OnChanges { public userService: UserService, private errorHandlingService: ErrorHandlingService, private githubService: GithubService, - private phaseService: PhaseService, - private electronService: ElectronService + private phaseService: PhaseService ) {} ngOnInit() { @@ -139,7 +137,7 @@ export class IssueDisputeComponent implements OnInit, OnChanges { } viewInGithub(): void { - this.electronService.openLink( + window.open( `https://github.com/${this.githubService.getRepoURL()}/issues/` + `${this.issue.id}#issuecomment-${this.issue.issueComment.id}` ); } diff --git a/tests/app/phase-team-response/issues-faulty/issues-faulty.component.spec.ts b/tests/app/phase-team-response/issues-faulty/issues-faulty.component.spec.ts index 0159ec8f..cd346cbc 100644 --- a/tests/app/phase-team-response/issues-faulty/issues-faulty.component.spec.ts +++ b/tests/app/phase-team-response/issues-faulty/issues-faulty.component.spec.ts @@ -17,7 +17,7 @@ describe('IssuesFaultyComponent', () => { const DUMMY_RESPONSE = 'dummy response'; beforeEach(() => { - issueService = new IssueService(null, null, null, null, null, null); + issueService = new IssueService(null, null, null, null, null); issueService.updateLocalStore(dummyIssue); issuesFaultyComponent = new IssuesFaultyComponent(issueService, userService, null); issuesFaultyComponent.ngOnInit(); diff --git a/tests/app/phase-team-response/issues-pending/issues-pending.component.spec.ts b/tests/app/phase-team-response/issues-pending/issues-pending.component.spec.ts index 0c764f78..50d02880 100644 --- a/tests/app/phase-team-response/issues-pending/issues-pending.component.spec.ts +++ b/tests/app/phase-team-response/issues-pending/issues-pending.component.spec.ts @@ -11,7 +11,7 @@ describe('IssuesPendingComponent', () => { const dummyTeam: Team = TEAM_4; let dummyIssue: Issue; let issuesPendingComponent: IssuesPendingComponent; - const issueService: IssueService = new IssueService(null, null, null, null, null, null); + const issueService: IssueService = new IssueService(null, null, null, null, null); const userService: UserService = new UserService(null, null, null); userService.currentUser = USER_Q; const DUMMY_DUPLICATE_ISSUE_ID = 1; diff --git a/tests/app/phase-team-response/issues-responded/issues-responded.component.spec.ts b/tests/app/phase-team-response/issues-responded/issues-responded.component.spec.ts index dc71ce7f..08ea0916 100644 --- a/tests/app/phase-team-response/issues-responded/issues-responded.component.spec.ts +++ b/tests/app/phase-team-response/issues-responded/issues-responded.component.spec.ts @@ -12,7 +12,7 @@ describe('IssuesRespondedComponent', () => { const DUMMY_RESPONSE = 'dummy response'; let dummyIssue: Issue; - const issueService = new IssueService(null, null, null, null, null, null); + const issueService = new IssueService(null, null, null, null, null); const userService = new UserService(null, null, null); userService.currentUser = USER_Q; const issuesRespondedComponent = new IssuesRespondedComponent(issueService, userService); diff --git a/tests/app/shared/issue-tables/search-filter.spec.ts b/tests/app/shared/issue-tables/search-filter.spec.ts index 078a1112..aa5c4725 100644 --- a/tests/app/shared/issue-tables/search-filter.spec.ts +++ b/tests/app/shared/issue-tables/search-filter.spec.ts @@ -45,7 +45,7 @@ describe('search-filter', () => { TABLE_COLUMNS.ASSIGNEE, TABLE_COLUMNS.DUPLICATED_ISSUES ]; - const issueService: IssueService = new IssueService(null, null, null, null, null, null); + const issueService: IssueService = new IssueService(null, null, null, null, null); beforeEach(() => { issueService.updateLocalStore(mediumSeverityIssueWithResponse); diff --git a/tests/services/logging.service.spec.ts b/tests/services/logging.service.spec.ts index d5fe3561..846eb93d 100644 --- a/tests/services/logging.service.spec.ts +++ b/tests/services/logging.service.spec.ts @@ -20,9 +20,7 @@ const mockDates = () => { }; const initializeLoggingService = () => { - const electronService = jasmine.createSpyObj('ElectronService', ['isElectron']); - electronService.isElectron = jasmine.createSpy('isElectron', () => false); - logger = new LoggingService(electronService); + logger = new LoggingService(); headerLog = `${logger.LOG_START_HEADER}\n${mockDate.toLocaleString()}`; sessionSeparator = logger.SESSION_LOG_SEPARATOR; }; diff --git a/tests/services/profile.service.spec.ts b/tests/services/profile.service.spec.ts index 455fd2c6..51d0d312 100644 --- a/tests/services/profile.service.spec.ts +++ b/tests/services/profile.service.spec.ts @@ -20,7 +20,7 @@ const INVALID_PROFILES = [ describe('ProfileService', () => { beforeEach(() => { - githubService = new GithubService(null, null, null, null); + githubService = new GithubService(null, null, null); profileService = new ProfileService(githubService); });