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

[No QA][TS migration] Migrate 'Visibility' lib to TypeScript #27437

Merged
merged 4 commits into from
Sep 20, 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
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
import ELECTRON_EVENTS from '../../../desktop/ELECTRON_EVENTS';
import {HasFocus, IsVisible, OnVisibilityChange} from './types';

/**
* Detects whether the app is visible or not. Electron supports document.visibilityState,
* but switching to another app while Electron is partially occluded will not trigger a state of hidden
* so we ask the main process synchronously whether the BrowserWindow.isFocused()
*
* @returns {Boolean}
*/
function isVisible() {
return window.electron.sendSync(ELECTRON_EVENTS.REQUEST_VISIBILITY);
}
const isVisible: IsVisible = () => !!window.electron.sendSync(ELECTRON_EVENTS.REQUEST_VISIBILITY);
Comment on lines -10 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we had to remove the named function here.

function isVisible(): boolean would be fine I guess.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From TS guidelines:

In modules with platform-specific implementations, create types.ts to define shared types. For platform-specific implementations, always define shared types that complies with all variants.

That's why IsVisible type was created in the first place and used here. I think the change was necessary.


/**
* @returns {Boolean}
*/
function hasFocus() {
return true;
}
const hasFocus: HasFocus = () => true;

/**
* Adds event listener for changes in visibility state
*
* @param {Function} callback
*
* @return {Function} removes the listener
*/
function onVisibilityChange(callback) {
const onVisibilityChange: OnVisibilityChange = (callback) => {
// Deliberately strip callback argument to be consistent across implementations
window.electron.on(ELECTRON_EVENTS.FOCUS, () => callback());
window.electron.on(ELECTRON_EVENTS.BLUR, () => callback());
Expand All @@ -34,7 +22,7 @@ function onVisibilityChange(callback) {
window.electron.removeAllListeners(ELECTRON_EVENTS.FOCUS);
window.electron.removeAllListeners(ELECTRON_EVENTS.BLUR);
};
}
};

export default {
isVisible,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,21 @@
// they do not use the Notification lib.

import {AppState} from 'react-native';
import {HasFocus, IsVisible, OnVisibilityChange} from './types';

/**
* @return {Boolean}
*/
const isVisible = () => AppState.currentState === 'active';
const isVisible: IsVisible = () => AppState.currentState === 'active';

/**
* @returns {Boolean}
*/
function hasFocus() {
return true;
}
const hasFocus: HasFocus = () => true;

/**
* Adds event listener for changes in visibility state
*
* @param {Function} callback
*
* @return {Function} removes the listener
*/
function onVisibilityChange(callback) {
const onVisibilityChange: OnVisibilityChange = (callback) => {
// Deliberately strip callback argument to be consistent across implementations
const subscription = AppState.addEventListener('change', () => callback());

return () => subscription.remove();
}
};

export default {
isVisible,
Expand Down
21 changes: 5 additions & 16 deletions src/libs/Visibility/index.js → src/libs/Visibility/index.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,25 @@
import {AppState} from 'react-native';
import {HasFocus, IsVisible, OnVisibilityChange} from './types';

/**
* Detects whether the app is visible or not.
*
* @returns {Boolean}
*/
function isVisible() {
return document.visibilityState === 'visible';
}
const isVisible: IsVisible = () => document.visibilityState === 'visible';

/**
* Whether the app is focused.
*
* @returns {Boolean}
*/
function hasFocus() {
return document.hasFocus();
}
const hasFocus: HasFocus = () => document.hasFocus();

/**
* Adds event listener for changes in visibility state
*
* @param {Function} callback
*
* @return {Function} removes the listener
*/
function onVisibilityChange(callback) {
const onVisibilityChange: OnVisibilityChange = (callback) => {
// Deliberately strip callback argument to be consistent across implementations
const subscription = AppState.addEventListener('change', () => callback());

return () => subscription.remove();
}
};

export default {
isVisible,
Expand Down
5 changes: 5 additions & 0 deletions src/libs/Visibility/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type IsVisible = () => boolean;
type HasFocus = () => boolean;
type OnVisibilityChange = (callback: () => void) => () => void;

export type {IsVisible, HasFocus, OnVisibilityChange};
18 changes: 18 additions & 0 deletions src/types/modules/electron.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// TODO: Move this type to desktop/contextBridge.js once it is converted to TS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we link to the tracking issue for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, here is a link to desktop files migration issue: #25333

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool thanks, we could also link it here for clarity

type ContextBridgeApi = {
send: (channel: string, data?: unknown) => void;
sendSync: (channel: string, data?: unknown) => unknown;
invoke: (channel: string, ...args: unknown) => Promise<unknown>;
on: (channel: string, func: () => void) => void;
removeAllListeners: (channel: string) => void;
};

declare global {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Window {
electron: ContextBridgeApi;
}
}

// We used the export {} line to mark this file as an external module
export {};
Loading