Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDA-4049 Taking screenshot - hiding fullscreen window #1690

Merged
merged 1 commit into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -243,4 +243,4 @@
"pre-commit": "pretty-quick --staged && npm run lint"
}
}
}
}
111 changes: 67 additions & 44 deletions src/app/screen-snippet-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
clipboard,
dialog,
ipcMain,
NativeImage,
nativeImage,
WebContents,
} from 'electron';
Expand Down Expand Up @@ -161,6 +162,7 @@ class ScreenSnippet {
await this.execCmd(this.captureUtil, this.captureUtilArgs);

if (windowHandler.isMana) {
winStore.restoreWindows(hideOnCapture);
logger.info(
'screen-snippet-handler: Attempting to extract image dimensions from: ' +
this.outputFilePath,
Expand All @@ -177,7 +179,6 @@ class ScreenSnippet {

if (dimensions.width === 0 && dimensions.height === 0) {
logger.info('screen-snippet-handler: no screen capture picture');
winStore.restoreWindowsOnCapturing(hideOnCapture);
return;
}

Expand Down Expand Up @@ -356,7 +357,7 @@ class ScreenSnippet {
'screen-snippet-handler: Snippet uploaded correctly, sending payload to SFE',
);
webContents.send('screen-snippet-data', payload);
winStore.focusWindowsSnippingFinished(hideOnCapture);
winStore.restoreWindows(hideOnCapture);
await this.verifyAndUpdateAlwaysOnTop();
} catch (error) {
await this.verifyAndUpdateAlwaysOnTop();
Expand Down Expand Up @@ -432,53 +433,21 @@ class ScreenSnippet {
clipboard: string;
},
) => {
if (isMac) {
windowHandler.closeSnippingToolWindow();
}
const filePath = path.join(
app.getPath('downloads'),
'symphonyImage-' + Date.now() + '.png',
);
const [, data] = saveAsData.clipboard.split(',');
const buffer = Buffer.from(data, 'base64');
const img = nativeImage.createFromBuffer(buffer);

const dialogResult = await dialog
.showSaveDialog(BrowserWindow.getFocusedWindow() as BrowserWindow, {
title: 'Select place to store your file',
defaultPath: filePath,
// defaultPath: path.join(__dirname, '../assets/'),
buttonLabel: 'Save',
// Restricting the user to only Text Files.
filters: [
{
name: 'Image file',
extensions: ['png'],
},
],
properties: [],
})
.then((file) => {
// Stating whether dialog operation was cancelled or not.
if (!file.canceled && file.filePath) {
// Creating and Writing to the sample.txt file
fs.writeFile(file.filePath.toString(), img.toPNG(), (err) => {
if (err) {
throw logger.error(
`screen-snippet-handler: cannot save file, failed with error: ${err}!`,
);
}

logger.info(`screen-snippet-handler: modal save opened!`);
});
}

return file;
})
.catch((err) => {
logger.error(
`screen-snippet-handler: cannot save file, failed with error: ${err}!`,
);

return undefined;
});
const dialogResult = await this.saveFile(
filePath,
img,
BrowserWindow.getFocusedWindow(),
);
if (dialogResult?.filePath) {
windowHandler.closeSnippingToolWindow();
}
Expand All @@ -496,7 +465,6 @@ class ScreenSnippet {
const windowObj = winStore.getWindowStore();
const currentWindowName = (currentWindowObj as ICustomBrowserWindow)
?.winName;

if (windowObj.windows.length < 1) {
const allWindows = BrowserWindow.getAllWindows();
let windowsArr: IWindowState[] = [];
Expand Down Expand Up @@ -531,12 +499,67 @@ class ScreenSnippet {
} else {
windowsArr = windowsArr.concat(mainArr);
}

winStore.setWindowStore({
windows: windowsArr,
});
}
};

/**
* Save image in a given location
* @param filePath where the image should be stored
* @param img the image
* @param parent parent window to attach save dialog
*/
private saveFile = (
filePath: string,
img: NativeImage,
parentWindow: BrowserWindow | null,
) => {
const saveOptions = {
title: 'Select place to store your file',
defaultPath: filePath,
// defaultPath: path.join(__dirname, '../assets/'),
buttonLabel: 'Save',
// Restricting the user to only Text Files.
filters: [
{
name: 'Image file',
extensions: ['png'],
},
],
properties: [],
};
const saveDialog =
!isMac && parentWindow
? dialog.showSaveDialog(parentWindow, saveOptions)
: dialog.showSaveDialog(saveOptions);
return saveDialog
.then((file) => {
// Stating whether dialog operation was cancelled or not.
if (!file.canceled && file.filePath) {
// Creating and Writing to the sample.txt file
fs.writeFile(file.filePath.toString(), img.toPNG(), (err) => {
if (err) {
throw logger.error(
`screen-snippet-handler: cannot save file, failed with error: ${err}!`,
);
}

logger.info(`screen-snippet-handler: modal save opened!`);
});
}

return file;
})
.catch((err) => {
logger.error(
`screen-snippet-handler: cannot save file, failed with error: ${err}!`,
);

return undefined;
});
};
}

const screenSnippet = new ScreenSnippet();
Expand Down
117 changes: 93 additions & 24 deletions src/app/stores/window-store.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { BrowserWindow } from 'electron';
import { isMac, isWindowsOS } from '../../common/env';
import { ICustomBrowserWindow, windowHandler } from '../window-handler';
import { getWindowByName } from '../window-utils';

export interface IWindowObject {
Expand All @@ -9,9 +11,11 @@ export interface IWindowState {
id: string;
minimized?: boolean;
focused?: boolean;
isFullScreen?: boolean;
}

export class WindowStore {
public windowsRestored: boolean = true;
private windowVariable: IWindowObject = {
windows: [],
};
Expand All @@ -35,47 +39,112 @@ export class WindowStore {

public hideWindowsOnCapturing = (hideOnCapture?: boolean) => {
if (hideOnCapture) {
this.windowsRestored = false;
const currentWindows = BrowserWindow.getAllWindows();

currentWindows.forEach((currentWindow) => {
currentWindow?.hide();
const isFullScreen = currentWindow.isFullScreen();
if (isFullScreen) {
this.hideFullscreenWindow(currentWindow);
} else {
currentWindow?.hide();
}
});
}
};

public focusWindowsSnippingFinished = (hideOnCapture?: boolean) => {
public restoreWindows = (hideOnCapture?: boolean) => {
if (hideOnCapture) {
const currentWindows = this.getWindowStore();
const currentWindow = currentWindows.windows.find(
const storedWindows = this.getWindowStore();
let currentWindow = storedWindows.windows.find(
(currentWindow) => currentWindow.focused,
);

if (currentWindow) {
if (!currentWindow.minimized) {
getWindowByName(currentWindow.id || '')?.show();
}

if (currentWindow.focused) {
getWindowByName(currentWindow.id || '')?.focus();
}
if (!currentWindow) {
// In case there is no window focused, we automatically focus on the main one.
currentWindow = storedWindows.windows.find(
(currentWindow) => currentWindow.id === 'main',
);
currentWindow!.focused = true;
}
}
};

public restoreWindowsOnCapturing = (hideOnCapture?: boolean) => {
if (hideOnCapture) {
const currentWindows = this.getWindowStore();
currentWindows.windows.forEach((currentWindow) => {
if (!currentWindow.minimized) {
getWindowByName(currentWindow.id || '')?.show();
}
let focusedWindowToRestore: ICustomBrowserWindow | undefined;

if (currentWindow.focused) {
getWindowByName(currentWindow.id || '')?.focus();
const fullscreenedWindows: IWindowState[] = [];
// Restoring all windows except focused one
storedWindows.windows.forEach((currentWindow) => {
if (currentWindow) {
const window: ICustomBrowserWindow | undefined = getWindowByName(
currentWindow.id || '',
) as ICustomBrowserWindow;
if (window) {
if (currentWindow.isFullScreen) {
fullscreenedWindows.push(currentWindow);
// Window should be shown before putting it in fullscreen on Windows
if (isWindowsOS) {
window.show();
}
} else if (!currentWindow.minimized && !currentWindow.focused) {
window.showInactive();
}
if (currentWindow.focused) {
focusedWindowToRestore = window;
}
}
}
});

// First item in array should be the focused window
fullscreenedWindows.sort((x: IWindowState, y: IWindowState) =>
x.focused === y.focused ? 0 : x.focused ? -1 : 1,
);
this.putWindowInFullScreenAndFocus(
fullscreenedWindows,
focusedWindowToRestore,
);

// Store reset
this.destroyWindowStore();
}
};

private hideFullscreenWindow = (window: BrowserWindow) => {
window.once('leave-full-screen', () => {
if (isMac) {
window.hide();
} else {
setTimeout(() => {
window.hide();
}, 0);
}
});
window.setFullScreen(false);
};

/**
* Restores windows that are in fullscreen and focus on the right window
* On macOS, windows in fullscreen need to be restore one by one
* @param windowsNames
*/
private putWindowInFullScreenAndFocus(
windows: IWindowState[],
windowToFocus?: BrowserWindow,
) {
if (windows.length) {
const windowDetails = windows[windows.length - 1];
const window: ICustomBrowserWindow | undefined = getWindowByName(
windowDetails.id || '',
) as ICustomBrowserWindow;
window.once('enter-full-screen', () => {
windows.pop();
this.putWindowInFullScreenAndFocus(windows, windowToFocus);
});
window.setFullScreen(true);
} else {
if (windowToFocus) {
windowToFocus?.show();
windowHandler.moveSnippingToolWindow(windowToFocus);
}
this.windowsRestored = true;
}
}
}
Loading