diff --git a/.github/workflows/deployment-actions.yml b/.github/workflows/deployment-actions.yml index 9ba4d9a..9406589 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 1b43aed..1ed2c82 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 38700ac..0000000 --- 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 03965ca..0000000 --- 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 0aea033..0000000 --- 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 6e6f522..0000000 --- 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 960b020..0000000 --- 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 e0c13a3..5869f34 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 7dce764..0000000 --- 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 1fb1275..0000000 --- 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 42419f9..243f3be 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 b86441c..ba6f950 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 5195127..c77aab4 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 de429fe..38d2a36 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 71011d0..e292672 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 730236e..cf8a9cb 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 53ebc93..0000000 --- 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 3fc70ff..0b287ce 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 ecfba3b..9a199a9 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 ea67a22..12c744d 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 76167fd..db45956 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 26a81a1..5b55cab 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 fbce78a..94335da 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 376057f..9f6588d 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 f9406a9..cca6816 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 0159ec8..cd346cb 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 0c764f7..50d0288 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 dc71ce7..08ea091 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 078a111..aa5c472 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 d5fe356..846eb93 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 455fd2c..51d0d31 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); });