diff --git a/api.ts b/api.ts index c72c4eba4..bc3881e4f 100644 --- a/api.ts +++ b/api.ts @@ -5,6 +5,8 @@ import { guid } from '@datorama/akita'; import { Playlist } from './src/app/playlist-uploader/playlist.interface'; import Nedb from 'nedb-promises-ts'; +const join = require('path').join; +const openAboutWindow = require('about-window').default; const db = new Nedb({ filename: 'data.db', autoload: true }); export class Api { @@ -56,6 +58,14 @@ export class Api { }); } }); + + ipcMain.on('show-about', () => { + openAboutWindow({ + icon_path: join(__dirname, 'dist/assets/icons/icon.png'), + copyright: 'Copyright (c) 2020 4gray', + package_json_dir: __dirname, + }); + }); } /** diff --git a/main.ts b/main.ts index c2b198bf8..ee66ca193 100644 --- a/main.ts +++ b/main.ts @@ -1,30 +1,32 @@ -import { app, BrowserWindow, screen } from 'electron'; +import { app, BrowserWindow, Menu, MenuItem, shell } from 'electron'; import * as path from 'path'; import * as url from 'url'; import { Api } from './api'; +const openAboutWindow = require('about-window').default; let win: BrowserWindow = null; const args = process.argv.slice(1), serve = args.some((val) => val === '--serve'); function createWindow(): BrowserWindow { - const electronScreen = screen; - const size = electronScreen.getPrimaryDisplay().workAreaSize; - // Create the browser window. win = new BrowserWindow({ - x: 0, - y: 0, - width: size.width, - height: size.height, + width: 1000, + height: 800, webPreferences: { nodeIntegration: true, allowRunningInsecureContent: serve ? true : false, }, resizable: true, darkTheme: true, + icon: path.join(__dirname, 'dist/assets/icons/icon.png'), + titleBarStyle: 'hidden', + frame: false, + minWidth: 900, + minHeight: 700, }); - win.setMenu(null); + const menu = createMenu(win); + Menu.setApplicationMenu(menu); if (serve) { win.webContents.openDevTools(); @@ -54,6 +56,67 @@ function createWindow(): BrowserWindow { return win; } +/** + * Creates context menu + * @param win browser window object + */ +function createMenu(win: BrowserWindow) { + const menu = new Menu(); + menu.append( + new MenuItem({ + label: 'File', + submenu: [ + { + label: 'Add playlist', + click: () => win.webContents.send('add-playlist-view'), + }, + { + type: 'separator', + }, + { + label: 'Exit', + click: () => app.quit(), + }, + ], + }) + ); + + menu.append( + new MenuItem({ + label: 'Help', + submenu: [ + { + label: 'Report a bug', + click: () => + shell.openExternal( + 'https://github.com/4gray/my-iptv-player-pwa' + ), + }, + { + label: 'Open DevTools', + click: () => win.webContents.openDevTools(), + }, + { + type: 'separator', + }, + { + label: 'About', + click: () => + openAboutWindow({ + icon_path: path.join( + __dirname, + 'dist/assets/icons/icon.png' + ), + copyright: 'Copyright (c) 2020 4gray', + package_json_dir: __dirname, + }), + }, + ], + }) + ); + return menu; +} + try { app.allowRendererProcessReuse = true; diff --git a/package-lock.json b/package-lock.json index fc2cfd389..e5adae8e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4062,6 +4062,11 @@ "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==", "dev": true }, + "about-window": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/about-window/-/about-window-1.13.4.tgz", + "integrity": "sha512-Ge7qBRzrmPbVJ2YarUfTrZEaSfhRjeVyFhmH9NqdNDjjgP0dcWwUprH61JWlDgcM3KaDn5zUzimG4YQh6vRocw==" + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", diff --git a/package.json b/package.json index 44def5913..ff0258c38 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "iptvnator", "version": "0.0.1", - "description": "IPTV player applicaion.", + "description": "IPTV player application.", "homepage": "https://github.com/4gray/my-iptv-player-pwa", "author": { "name": "4gray", @@ -102,6 +102,7 @@ "@angular/material": "10.1.2", "@datorama/akita": "5.2.2", "@types/hls.js": "0.13.0", + "about-window": "1.13.4", "axios": "0.19.2", "custom-electron-titlebar": "3.2.3", "hls.js": "0.14.8", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 406c07c5d..a8e75640f 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -4,9 +4,13 @@ import { AppConfig } from '../environments/environment'; import { akitaDevtools } from '@datorama/akita'; import { Titlebar, Color } from 'custom-electron-titlebar'; import { ElectronService } from './services/electron.service'; +import { Router } from '@angular/router'; +// create custom title bar new Titlebar({ backgroundColor: Color.fromHex('#000'), + itemBackgroundColor: Color.fromHex('#222'), + enableMnemonics: true, }); @Component({ @@ -18,6 +22,7 @@ export class AppComponent { constructor( private electronService: ElectronService, private ngZone: NgZone, + private router: Router, private translate: TranslateService ) { if (!AppConfig.production) { @@ -40,5 +45,10 @@ export class AppComponent { } else { console.log('Run in browser'); } + this.electronService.ipcRenderer.on('add-playlist-view', () => { + this.ngZone.run(() => { + this.router.navigateByUrl('/', { skipLocationChange: true }); + }); + }); } } diff --git a/src/app/channel-list-container/channel-list-container.component.html b/src/app/channel-list-container/channel-list-container.component.html index 25633c1d4..03b98b8cf 100644 --- a/src/app/channel-list-container/channel-list-container.component.html +++ b/src/app/channel-list-container/channel-list-container.component.html @@ -12,8 +12,8 @@ - - +

{{ i+1 + '. ' + channel?.name || 'Unnamed Channel' }} @@ -23,7 +23,7 @@ --> - + @@ -42,8 +42,8 @@ {{ i+1 + '. ' + channel?.name || 'Unnamed Channel' }}

+ star{{ channel.fav ? '' : '_outline' }} + -->
diff --git a/src/app/channel-list-container/channel-list-container.component.scss b/src/app/channel-list-container/channel-list-container.component.scss index 61fbc19f5..a9ee4a0c4 100644 --- a/src/app/channel-list-container/channel-list-container.component.scss +++ b/src/app/channel-list-container/channel-list-container.component.scss @@ -26,6 +26,9 @@ margin: 3px 10px !important; } +.scroll-viewport { + min-height: calc(100vh - 142px); +} ::ng-deep { .mat-tab-group { diff --git a/src/app/material.module.ts b/src/app/material.module.ts index d27ebc893..b2db6847b 100644 --- a/src/app/material.module.ts +++ b/src/app/material.module.ts @@ -10,6 +10,7 @@ import { MatSidenavModule } from '@angular/material/sidenav'; import { MatTabsModule } from '@angular/material/tabs'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { ScrollingModule } from '@angular/cdk/scrolling'; @NgModule({ exports: [ @@ -24,6 +25,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar'; MatSnackBarModule, MatTabsModule, MatToolbarModule, + ScrollingModule, ], }) export class MaterialModule {} diff --git a/src/app/video-player/video-player.component.html b/src/app/video-player/video-player.component.html index 411cc24fd..853213272 100644 --- a/src/app/video-player/video-player.component.html +++ b/src/app/video-player/video-player.component.html @@ -28,6 +28,7 @@ {{ (activeChannel$ | async)?.name}}
+ diff --git a/src/app/video-player/video-player.component.ts b/src/app/video-player/video-player.component.ts index e847964de..81d167a12 100644 --- a/src/app/video-player/video-player.component.ts +++ b/src/app/video-player/video-player.component.ts @@ -11,6 +11,9 @@ import * as _ from 'lodash'; styleUrls: ['./video-player.component.css'], }) export class VideoPlayerComponent implements OnInit { + /** electrons ipc reference */ + renderer = window.require('electron').ipcRenderer; + /** Channels list */ channels$: Observable; @@ -72,4 +75,11 @@ export class VideoPlayerComponent implements OnInit { }); } } + + /** + * Opens about application dialog + */ + openAbout(): void { + this.renderer.send('show-about'); + } }