mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
feat: SDA-1995: implement download manager for Mana (#982)
* SDA-1995: add download handler functionality for Mana Signed-off-by: Vishwas Shashidhar <vishwas.shashidhar@symphony.com> * SDA-1995: add unit tests Signed-off-by: Vishwas Shashidhar <vishwas.shashidhar@symphony.com> * SDA-1995: fix unit tests on Windows Signed-off-by: Vishwas Shashidhar <vishwas.shashidhar@symphony.com> * SDA-1955: address PR comments Signed-off-by: Vishwas Shashidhar <vishwas.shashidhar@symphony.com>
This commit is contained in:
committed by
GitHub
parent
0921cca4b1
commit
8f518e3936
54
spec/downloadHandler.spec.ts
Normal file
54
spec/downloadHandler.spec.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
jest.mock('electron-log');
|
||||
|
||||
jest.mock('../src/app/window-handler', () => {
|
||||
return {
|
||||
windowHandler: {
|
||||
setIsAutoReload: jest.fn(() => true),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../src/app/window-utils', () => {
|
||||
return {
|
||||
windowExists: jest.fn(() => true),
|
||||
};
|
||||
});
|
||||
|
||||
describe('download handler', () => {
|
||||
let downloadHandlerInstance;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
// I did it for reset module imported between tests
|
||||
const { downloadHandler } = require('../src/app/download-handler');
|
||||
downloadHandlerInstance = downloadHandler;
|
||||
});
|
||||
|
||||
afterAll((done) => {
|
||||
done();
|
||||
});
|
||||
|
||||
it('should call `sendDownloadCompleted` when download succeeds', () => {
|
||||
const spy: jest.SpyInstance = jest.spyOn(downloadHandlerInstance, 'sendDownloadCompleted')
|
||||
.mockImplementation(() => jest.fn());
|
||||
|
||||
const data: any = {
|
||||
_id: '121312-123912321-1231231',
|
||||
savedPath: '/abc/def/123.txt',
|
||||
total: '1234556',
|
||||
fileName: 'Test.txt',
|
||||
};
|
||||
|
||||
downloadHandlerInstance.onDownloadSuccess(data);
|
||||
expect(spy).toBeCalled();
|
||||
});
|
||||
|
||||
it('should call `sendDownloadFailed` when download fails', () => {
|
||||
const spy: jest.SpyInstance = jest.spyOn(downloadHandlerInstance, 'sendDownloadFailed')
|
||||
.mockImplementation(() => jest.fn());
|
||||
|
||||
downloadHandlerInstance.onDownloadFailed();
|
||||
expect(spy).toBeCalled();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
import { activityDetection } from '../src/app/activity-detection';
|
||||
import { downloadHandler } from '../src/app/download-handler';
|
||||
import '../src/app/main-api-handler';
|
||||
import { protocolHandler } from '../src/app/protocol-handler';
|
||||
import { screenSnippet } from '../src/app/screen-snippet-handler';
|
||||
@@ -94,6 +95,17 @@ jest.mock('../src/app/activity-detection', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../src/app/download-handler', () => {
|
||||
return {
|
||||
downloadHandler: {
|
||||
setWindow: jest.fn(),
|
||||
openFile: jest.fn(),
|
||||
showInFinder: jest.fn(),
|
||||
clearDownloadItems: jest.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../src/common/i18n');
|
||||
|
||||
describe('main api handler', () => {
|
||||
@@ -201,6 +213,67 @@ describe('main api handler', () => {
|
||||
expect(spy).toBeCalledWith(...expectedValue);
|
||||
});
|
||||
|
||||
it('should call `registerDownloadHandler` correctly', () => {
|
||||
const spy = jest.spyOn(downloadHandler, 'setWindow');
|
||||
const value = {
|
||||
cmd: apiCmds.registerDownloadHandler,
|
||||
};
|
||||
const expectedValue = [ { send: expect.any(Function) } ];
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
expect(spy).toBeCalledWith(...expectedValue);
|
||||
});
|
||||
|
||||
it('should call `openFile` correctly', () => {
|
||||
const spy = jest.spyOn(downloadHandler, 'openFile');
|
||||
const value = {
|
||||
cmd: apiCmds.openDownloadItem,
|
||||
id: '12345678',
|
||||
};
|
||||
const expectedValue = '12345678';
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
expect(spy).toBeCalledWith(expectedValue);
|
||||
});
|
||||
|
||||
it('should not call `openFile` if id is not a string', () => {
|
||||
const spy = jest.spyOn(downloadHandler, 'openFile');
|
||||
const value = {
|
||||
cmd: apiCmds.openDownloadItem,
|
||||
id: 10,
|
||||
};
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
expect(spy).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('should call `showFile` correctly', () => {
|
||||
const spy = jest.spyOn(downloadHandler, 'showInFinder');
|
||||
const value = {
|
||||
cmd: apiCmds.showDownloadItem,
|
||||
id: `12345678`,
|
||||
};
|
||||
const expectedValue = '12345678';
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
expect(spy).toBeCalledWith(expectedValue);
|
||||
});
|
||||
|
||||
it('should not call `showFile` if id is not a string', () => {
|
||||
const spy = jest.spyOn(downloadHandler, 'showInFinder');
|
||||
const value = {
|
||||
cmd: apiCmds.showDownloadItem,
|
||||
id: 10,
|
||||
};
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
expect(spy).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('should call `clearItems` correctly', () => {
|
||||
const spy = jest.spyOn(downloadHandler, 'clearDownloadItems');
|
||||
const value = {
|
||||
cmd: apiCmds.clearDownloadItems,
|
||||
};
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
expect(spy).toBeCalled();
|
||||
});
|
||||
|
||||
it('should call `showNotificationSettings` correctly', () => {
|
||||
const spy = jest.spyOn(windowHandler, 'createNotificationSettingsWindow');
|
||||
const value = {
|
||||
|
||||
168
src/app/download-handler.ts
Normal file
168
src/app/download-handler.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import { BrowserWindow, dialog, shell } from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import { i18n } from '../common/i18n';
|
||||
import { logger } from '../common/logger';
|
||||
import { windowExists } from './window-utils';
|
||||
|
||||
const DOWNLOAD_MANAGER_NAMESPACE = 'DownloadManager';
|
||||
|
||||
export interface IDownloadManager {
|
||||
_id: string;
|
||||
fileName: string;
|
||||
fileDisplayName?: string;
|
||||
savedPath: string;
|
||||
total: string;
|
||||
flashing?: boolean;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
class DownloadHandler {
|
||||
|
||||
/**
|
||||
* Checks and constructs file name
|
||||
*
|
||||
* @param fileName {String} Filename
|
||||
* @param item {IDownloadManager} Download Item
|
||||
*/
|
||||
private static getFileDisplayName(fileName: string, item: IDownloadManager): string {
|
||||
/* If it exists, add a count to the name like how Chrome does */
|
||||
if (item.count && item.count > 0) {
|
||||
const extLastIndex = fileName.lastIndexOf('.');
|
||||
const fileCount = ' (' + item.count + ')';
|
||||
|
||||
fileName = fileName.slice(0, extLastIndex) + fileCount + fileName.slice(extLastIndex);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show dialog for failed cases
|
||||
*/
|
||||
private static async showDialog(): Promise<void> {
|
||||
const focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
const message = i18n.t('The file you are trying to open cannot be found in the specified path.', DOWNLOAD_MANAGER_NAMESPACE)();
|
||||
const title = i18n.t('File not Found', DOWNLOAD_MANAGER_NAMESPACE)();
|
||||
|
||||
if (!focusedWindow || !windowExists(focusedWindow)) {
|
||||
return;
|
||||
}
|
||||
await dialog.showMessageBox(focusedWindow, {
|
||||
message,
|
||||
title,
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
|
||||
private window!: Electron.WebContents | null;
|
||||
private items: IDownloadManager[] = [];
|
||||
|
||||
/**
|
||||
* Sets the window for the download handler
|
||||
* @param window Window object
|
||||
*/
|
||||
public setWindow(window: Electron.WebContents): void {
|
||||
this.window = window;
|
||||
logger.info(`download-handler: Initialized download handler`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the downloaded file
|
||||
*
|
||||
* @param id {string} File ID
|
||||
*/
|
||||
public openFile(id: string): void {
|
||||
const filePath = this.getFilePath(id);
|
||||
|
||||
const openResponse = fs.existsSync(`${filePath}`) && shell.openItem(`${filePath}`);
|
||||
if (openResponse) {
|
||||
return;
|
||||
}
|
||||
|
||||
DownloadHandler.showDialog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the downloaded file in finder/explorer
|
||||
*
|
||||
* @param id {string} File ID
|
||||
*/
|
||||
public showInFinder(id: string): void {
|
||||
const filePath = this.getFilePath(id);
|
||||
|
||||
if (fs.existsSync(filePath)) {
|
||||
shell.showItemInFolder(filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
DownloadHandler.showDialog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears download items
|
||||
*/
|
||||
public clearDownloadItems(): void {
|
||||
this.items = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a successful download
|
||||
* @param item Download item
|
||||
*/
|
||||
public onDownloadSuccess(item: IDownloadManager): void {
|
||||
let itemCount = 0;
|
||||
for (const existingItem of this.items) {
|
||||
if (item.fileName === existingItem.fileName) {
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
item.count = itemCount;
|
||||
item.fileDisplayName = DownloadHandler.getFileDisplayName(item.fileName, item);
|
||||
this.items.push(item);
|
||||
this.sendDownloadCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a failed download
|
||||
*/
|
||||
public onDownloadFailed(): void {
|
||||
this.sendDownloadFailed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send download completed event to the renderer process
|
||||
*/
|
||||
private sendDownloadCompleted(): void {
|
||||
if (this.window && !this.window.isDestroyed()) {
|
||||
logger.info(`download-handler: Download completed! Informing the client!`);
|
||||
this.window.send('download-completed', this.items.map((item) => {
|
||||
return {id: item._id, fileDisplayName: item.fileDisplayName, fileSize: item.total};
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send download failed event to the renderer process
|
||||
*/
|
||||
private sendDownloadFailed(): void {
|
||||
if (this.window && !this.window.isDestroyed()) {
|
||||
logger.info(`download-handler: Download failed! Informing the client!`);
|
||||
this.window.send('download-failed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file path for the given item
|
||||
* @param id ID of the item
|
||||
*/
|
||||
private getFilePath(id: string): string {
|
||||
const fileIndex = this.items.findIndex((item) => {
|
||||
return item._id === id;
|
||||
});
|
||||
|
||||
return this.items[fileIndex].savedPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const downloadHandler = new DownloadHandler();
|
||||
export { downloadHandler };
|
||||
@@ -6,6 +6,7 @@ import { logger } from '../common/logger';
|
||||
import { activityDetection } from './activity-detection';
|
||||
import { analytics } from './analytics-handler';
|
||||
import { CloudConfigDataTypes, config, ICloudConfig } from './config-handler';
|
||||
import { downloadHandler } from './download-handler';
|
||||
import { memoryMonitor } from './memory-monitor';
|
||||
import { protocolHandler } from './protocol-handler';
|
||||
import { finalizeLogExports, registerLogRetriever } from './reports-handler';
|
||||
@@ -85,6 +86,9 @@ ipcMain.on(apiName.symphonyApi, async (event: Electron.IpcMainEvent, arg: IApiAr
|
||||
activityDetection.setWindowAndThreshold(event.sender, arg.period);
|
||||
}
|
||||
break;
|
||||
case apiCmds.registerDownloadHandler:
|
||||
downloadHandler.setWindow(event.sender);
|
||||
break;
|
||||
case apiCmds.showNotificationSettings:
|
||||
if (typeof arg.windowName === 'string') {
|
||||
windowHandler.createNotificationSettingsWindow(arg.windowName);
|
||||
@@ -147,6 +151,19 @@ ipcMain.on(apiName.symphonyApi, async (event: Electron.IpcMainEvent, arg: IApiAr
|
||||
downloadManagerAction(arg.type, arg.path);
|
||||
}
|
||||
break;
|
||||
case apiCmds.openDownloadItem:
|
||||
if (typeof arg.id === 'string') {
|
||||
downloadHandler.openFile(arg.id);
|
||||
}
|
||||
break;
|
||||
case apiCmds.showDownloadItem:
|
||||
if (typeof arg.id === 'string') {
|
||||
downloadHandler.showInFinder(arg.id);
|
||||
}
|
||||
break;
|
||||
case apiCmds.clearDownloadItems:
|
||||
downloadHandler.clearDownloadItems();
|
||||
break;
|
||||
case apiCmds.isMisspelled:
|
||||
if (typeof arg.word === 'string') {
|
||||
event.returnValue = windowHandler.spellchecker ? windowHandler.spellchecker.isMisspelled(arg.word) : false;
|
||||
|
||||
@@ -14,6 +14,7 @@ import { getGuid } from '../common/utils';
|
||||
import { whitelistHandler } from '../common/whitelist-handler';
|
||||
import { autoLaunchInstance } from './auto-launch-controller';
|
||||
import { CloudConfigDataTypes, config, IConfig, ICustomRectangle } from './config-handler';
|
||||
import { downloadHandler, IDownloadManager } from './download-handler';
|
||||
import { memoryMonitor } from './memory-monitor';
|
||||
import { screenSnippet } from './screen-snippet-handler';
|
||||
import { updateAlwaysOnTop } from './window-actions';
|
||||
@@ -400,13 +401,30 @@ export const handleDownloadManager = (_event, item: Electron.DownloadItem, webCo
|
||||
// Send file path when download is complete
|
||||
item.once('done', (_e, state) => {
|
||||
if (state === 'completed') {
|
||||
const data = {
|
||||
const data: IDownloadManager = {
|
||||
_id: getGuid(),
|
||||
savedPath: item.getSavePath() || '',
|
||||
total: filesize(item.getTotalBytes() || 0),
|
||||
fileName: item.getFilename() || 'No name',
|
||||
};
|
||||
logger.info('window-utils: Download completed, informing download manager');
|
||||
webContents.send('downloadCompleted', data);
|
||||
downloadHandler.onDownloadSuccess(data);
|
||||
} else {
|
||||
logger.info('window-utils: Download failed, informing download manager');
|
||||
downloadHandler.onDownloadFailed();
|
||||
}
|
||||
});
|
||||
|
||||
item.on('updated', (_e, state) => {
|
||||
if (state === 'interrupted') {
|
||||
logger.info('window-utils: Download is interrupted but can be resumed');
|
||||
} else if (state === 'progressing') {
|
||||
if (item.isPaused()) {
|
||||
logger.info('window-utils: Download is paused');
|
||||
} else {
|
||||
logger.info(`window-utils: Received bytes: ${item.getReceivedBytes()}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -38,6 +38,10 @@ export enum apiCmds {
|
||||
setCloudConfig = 'set-cloud-config',
|
||||
getCPUUsage = 'get-cpu-usage',
|
||||
checkMediaPermission = 'check-media-permission',
|
||||
registerDownloadHandler = 'register-download-handler',
|
||||
openDownloadItem = 'open-download-item',
|
||||
showDownloadItem = 'show-download-item',
|
||||
clearDownloadItems = 'clear-download-items',
|
||||
}
|
||||
|
||||
export enum apiName {
|
||||
@@ -151,6 +155,16 @@ export interface ICPUUsage {
|
||||
idleWakeupsPerSecond: number;
|
||||
}
|
||||
|
||||
export interface IDownloadManager {
|
||||
_id: string;
|
||||
fileName: string;
|
||||
fileDisplayName: string;
|
||||
savedPath: string;
|
||||
total: number;
|
||||
flashing?: boolean;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
export interface IMediaPermission {
|
||||
camera: string;
|
||||
microphone: string;
|
||||
|
||||
@@ -95,6 +95,9 @@
|
||||
<div id="footer" class="hidden">
|
||||
<div id="download-manager-footer" class="download-bar"></div>
|
||||
</div>
|
||||
<input type="button" id="open-download-item" value="Open Latest Item">
|
||||
<input type="button" id="show-download-item" value="Show Latest Item in Finder">
|
||||
<input type="button" id="close-download-manager" value="Close Download Manager">
|
||||
<br>
|
||||
<hr>
|
||||
<p>
|
||||
@@ -211,6 +214,10 @@
|
||||
sendLogs: 'send-logs',
|
||||
registerAnalyticHandler: 'register-analytic-handler',
|
||||
registerActivityDetection: 'register-activity-detection',
|
||||
registerDownloadHandler: 'register-download-handler',
|
||||
openDownloadItem: 'open-download-item',
|
||||
showDownloadItem: 'show-download-item',
|
||||
clearDownloadItems: 'clear-download-items',
|
||||
showNotificationSettings: 'show-notification-settings',
|
||||
sanitize: 'sanitize',
|
||||
bringToFront: 'bring-to-front',
|
||||
@@ -539,6 +546,10 @@
|
||||
handleResponse(data);
|
||||
console.log(event.data);
|
||||
break;
|
||||
case 'download-handler-callback':
|
||||
onDownload(data);
|
||||
console.log(event.data);
|
||||
break;
|
||||
default:
|
||||
console.log(event.data);
|
||||
}
|
||||
@@ -580,6 +591,21 @@
|
||||
console.log('bounds changed for=', arg)
|
||||
}
|
||||
|
||||
if (window.ssf) {
|
||||
ssf.registerDownloadHandler(onDownload);
|
||||
} else {
|
||||
postMessage(apiCmds.registerDownloadHandler);
|
||||
}
|
||||
|
||||
function onDownload(data) {
|
||||
if (data && data.status === 'download-completed') {
|
||||
items = data.items;
|
||||
console.log('Download completed!', data.items);
|
||||
} else {
|
||||
console.log('Download failed!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protocol handler
|
||||
*/
|
||||
@@ -804,6 +830,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
let items = [];
|
||||
/**
|
||||
* Download Manager api handler
|
||||
*/
|
||||
@@ -831,7 +858,40 @@
|
||||
const filename = "bye.txt";
|
||||
const text = document.getElementById("text-val").value;
|
||||
download(filename, text);
|
||||
}, false);
|
||||
}, false)
|
||||
|
||||
document.getElementById('open-download-item').addEventListener('click', () => {
|
||||
if (!items || items.length < 1) {
|
||||
alert('No files downloaded! Try again!');
|
||||
}
|
||||
const id = items[items.length - 1].id;
|
||||
if (window.ssf) {
|
||||
window.ssf.openDownloadItem(id);
|
||||
} else {
|
||||
postMessage(apiCmds.openDownloadItem, id);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('show-download-item').addEventListener('click', () => {
|
||||
if (!items || items.length < 1) {
|
||||
alert('No files downloaded! Try again!');
|
||||
}
|
||||
const id = items[items.length - 1].id;
|
||||
if (window.ssf) {
|
||||
window.ssf.showDownloadItem(id);
|
||||
} else {
|
||||
postMessage(apiCmds.showDownloadItem, id);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('close-download-manager').addEventListener('click', () => {
|
||||
items = [];
|
||||
if (window.ssf) {
|
||||
window.ssf.clearDownloadItems();
|
||||
} else {
|
||||
postMessage(apiCmds.clearDownloadItems);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</html>
|
||||
|
||||
@@ -61,6 +61,7 @@ export class AppBridge {
|
||||
onNotificationCallback: (event, data) => this.notificationCallback(event, data),
|
||||
onAnalyticsEventCallback: (data) => this.analyticsEventCallback(data),
|
||||
restartFloater: (data) => this.restartFloater(data),
|
||||
onDownloadItemCallback: (data) => this.onDownloadItemCallback(data),
|
||||
};
|
||||
|
||||
constructor() {
|
||||
@@ -108,6 +109,19 @@ export class AppBridge {
|
||||
ssf.setBadgeCount(data as number);
|
||||
}
|
||||
break;
|
||||
case apiCmds.openDownloadItem:
|
||||
if (typeof data === 'string') {
|
||||
ssf.openDownloadItem(data as string);
|
||||
}
|
||||
break;
|
||||
case apiCmds.showDownloadItem:
|
||||
if (typeof data === 'string') {
|
||||
ssf.showDownloadItem(data as string);
|
||||
}
|
||||
break;
|
||||
case apiCmds.clearDownloadItems:
|
||||
ssf.clearDownloadItems();
|
||||
break;
|
||||
case apiCmds.setLocale:
|
||||
if (typeof data === 'string') {
|
||||
ssf.setLocale(data as string);
|
||||
@@ -116,6 +130,9 @@ export class AppBridge {
|
||||
case apiCmds.registerActivityDetection:
|
||||
ssf.registerActivityDetection(data as number, this.callbackHandlers.onActivityCallback);
|
||||
break;
|
||||
case apiCmds.registerDownloadHandler:
|
||||
ssf.registerDownloadHandler(this.callbackHandlers.onDownloadItemCallback);
|
||||
break;
|
||||
case apiCmds.openScreenSnippet:
|
||||
ssf.openScreenSnippet(this.callbackHandlers.onScreenSnippetCallback);
|
||||
break;
|
||||
@@ -243,6 +260,14 @@ export class AppBridge {
|
||||
this.broadcastMessage('analytics-event-callback', arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast download item event
|
||||
* @param arg {object}
|
||||
*/
|
||||
private onDownloadItemCallback(arg: object): void {
|
||||
this.broadcastMessage('download-handler-callback', arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast to restart floater event with data
|
||||
* @param arg {IAnalyticsData}
|
||||
|
||||
@@ -8,7 +8,7 @@ interface IDownloadManager {
|
||||
_id: string;
|
||||
fileName: string;
|
||||
savedPath: string;
|
||||
total: number;
|
||||
total: string;
|
||||
flashing: boolean;
|
||||
count: number;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ if (ssfWindow.ssf) {
|
||||
bringToFront: ssfWindow.ssf.bringToFront,
|
||||
getVersionInfo: ssfWindow.ssf.getVersionInfo,
|
||||
registerActivityDetection: ssfWindow.ssf.registerActivityDetection,
|
||||
registerDownloadHandler: ssfWindow.ssf.registerDownloadHandler,
|
||||
registerBoundsChange: ssfWindow.ssf.registerBoundsChange,
|
||||
registerLogger: ssfWindow.ssf.registerLogger,
|
||||
registerProtocolHandler: ssfWindow.ssf.registerProtocolHandler,
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
apiName,
|
||||
IBadgeCount,
|
||||
IBoundsChange,
|
||||
ICPUUsage,
|
||||
ICPUUsage, IDownloadManager,
|
||||
ILogMsg,
|
||||
IMediaPermission,
|
||||
IRestartFloaterData,
|
||||
@@ -36,6 +36,7 @@ export interface ILocalObject {
|
||||
ipcRenderer;
|
||||
logger?: (msg: ILogMsg, logLevel: LogLevel, showInConsole: boolean) => void;
|
||||
activityDetectionCallback?: (arg: number) => void;
|
||||
downloadManagerCallback?: (arg?: any) => void;
|
||||
screenSnippetCallback?: (arg: IScreenSnippet) => void;
|
||||
boundsChangeCallback?: (arg: IBoundsChange) => void;
|
||||
screenSharingIndicatorCallback?: (arg: IScreenSharingIndicator) => void;
|
||||
@@ -101,6 +102,26 @@ const throttledSetCloudConfig = throttle((data) => {
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
const throttledOpenDownloadItem = throttle((id: string) => {
|
||||
ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openDownloadItem,
|
||||
id,
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
const throttledShowDownloadItem = throttle((id: string) => {
|
||||
ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.showDownloadItem,
|
||||
id,
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
const throttledClearDownloadItems = throttle(() => {
|
||||
ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.clearDownloadItems,
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
let cryptoLib: ICryptoLib | null;
|
||||
try {
|
||||
cryptoLib = remote.require('../app/crypto-handler.js').cryptoLibrary;
|
||||
@@ -215,6 +236,20 @@ export class SSFApi {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the download handler
|
||||
* @param downloadManagerCallback Callback to be triggered by the download handler
|
||||
*/
|
||||
public registerDownloadHandler(downloadManagerCallback: (arg: any) => void): void {
|
||||
if (typeof downloadManagerCallback === 'function') {
|
||||
local.downloadManagerCallback = downloadManagerCallback;
|
||||
}
|
||||
|
||||
local.ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.registerDownloadHandler,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows JS to register a callback to be invoked when size/positions
|
||||
* changes for any pop-out window (i.e., window.open). The main
|
||||
@@ -487,6 +522,29 @@ export class SSFApi {
|
||||
throttledSetCloudConfig(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Downloaded item
|
||||
* @param id ID of the item
|
||||
*/
|
||||
public openDownloadItem(id: string): void {
|
||||
throttledOpenDownloadItem(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show downloaded item in finder / explorer
|
||||
* @param id ID of the item
|
||||
*/
|
||||
public showDownloadItem(id: string): void {
|
||||
throttledShowDownloadItem(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears downloaded items
|
||||
*/
|
||||
public clearDownloadItems(): void {
|
||||
throttledClearDownloadItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* get CPU usage
|
||||
*/
|
||||
@@ -596,6 +654,18 @@ local.ipcRenderer.on('activity', (_event: Event, idleTime: number) => {
|
||||
}
|
||||
});
|
||||
|
||||
local.ipcRenderer.on('download-completed', (_event: Event, downloadItems: IDownloadManager[]) => {
|
||||
if (typeof downloadItems === 'object' && typeof local.downloadManagerCallback === 'function') {
|
||||
local.downloadManagerCallback({status: 'download-completed', items: downloadItems});
|
||||
}
|
||||
});
|
||||
|
||||
local.ipcRenderer.on('download-failed', (_event: Event) => {
|
||||
if (typeof local.downloadManagerCallback === 'function') {
|
||||
local.downloadManagerCallback({status: 'download-failed'});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered by the main process
|
||||
* Whenever some Window position or dimension changes
|
||||
|
||||
Reference in New Issue
Block a user