Skip to content

Commit

Permalink
🎉 Make fade-in and fade-out animation configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
Schneegans committed Oct 11, 2024
1 parent 2fc8066 commit 9054780
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 43 deletions.
4 changes: 3 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ This changelog follows the rules of [Keep a Changelog](http://keepachangelog.com

- **Paste-Text Action!** You can now paste text into the currently focused window using the new "Paste Text" action. This uses your clipboard internally, so it can paste any text including special characters like emojis 🎊!
- **Support for base64 icons!** This allows you to directly embed base64 encoded images. This will be especially helpful for menus which are dynamically generated via some sort of API in the future. Use `"base64"` as the icon theme and provide the base64 encoded image as the `"icon"`. This will be a string starting with something like `"data:image/svg+xml;base64, ..."`. This even supports animated gifs!
- Added an option to the menu editor which **allows warping the mouse pointer to the center of the menu** when the menu is opened in centered mode. This allows to directly engage in turbor mode even if the menu is shown at the center of the screen.
- Added an option to the menu editor which **allows warping the mouse pointer to the center of the menu** when the menu is opened in centered mode. This allows to directly engage in turbo mode even if the menu is shown at the center of the screen.
- It is now possible to **change the fade-in and fade-out duration of the menu!** For now, it is only possible to change this via the `fadeInDuration` and `fadeOutDuration` properties in the `config.json` file. The values are given in milliseconds and default to 150ms and 200ms respectively. In the future, this will be exposed in the settings UI.
- Icon themes are now also loaded from `resources/app/.webpack/renderer/assets/icon-themes/` in the installation directory. This can be interesting if you are packaging icon themes using a package manager. However, as an end user, you should not put your icon themes there, as they might be overwritten during an update.
- Support for symbolic links in the `icon-themes` directory. You can now create a symbolic link to an icon theme in the `icon-themes` directory and Kando will load the icons from the linked directory.
- Several **translation updates**. Thanks to all the contributors!

#### :wrench: Changed

- The default fade-out animation is now faster. This should make the menu feel more responsive especially for actions which are executed only after the menu is fully hidden.
- Menu themes are now also loaded from symbolic-link subdirectories in the `menu-themes` directories.
- The "Command" actions will now be executed using the user's home directory as the working directory. Before Kando's installation directory was used.

Expand Down
2 changes: 2 additions & 0 deletions docs/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Property | Default Value | Description
`enableDarkModeForMenuThemes` | `false` | Whether Kando should use the dark menu theme if the system is in dark mode.
`sidebarVisible` | `true` | Whether the left sidebar is currently visible.
`zoomFactor` | `1.0` | The zoom factor of the menu. This can be used to scale the menu on high-resolution screens.
`fadeInDuration` | `150` | The duration of the fade-in animation in milliseconds. Set to `0` to disable the animation.
`fadeOutDuration` | `200` | The duration of the fade-out animation in milliseconds. Set to `0` to disable the animation. Some actions are only executed after the fade-out animation has finished, so reducing this value can make the menu much "snappier".
`enableVersionCheck` | `true` | If set to `true`, Kando will check for new version regularly, and show a notification if a new version is available.

## The Menu Configuration: `menus.json`
Expand Down
6 changes: 6 additions & 0 deletions src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,4 +426,10 @@ export interface IAppSettings {

/** A scale factor for the menu. */
zoomFactor: number;

/** The duration of the fade in animation in milliseconds. */
fadeInDuration: number;

/** The duration of the fade out animation in milliseconds. */
fadeOutDuration: number;
}
15 changes: 11 additions & 4 deletions src/main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ export class KandoApp {
sidebarVisible: true,
enableVersionCheck: true,
zoomFactor: 1,
fadeInDuration: 150,
fadeOutDuration: 200,
},
});

Expand Down Expand Up @@ -543,6 +545,11 @@ export class KandoApp {
// system. In development mode, the app is loaded from the webpack dev server.
// Hence, we have to disable webSecurity in development mode.
webSecurity: process.env.NODE_ENV !== 'development',
// Background throttling is disabled to make sure that the menu is properly
// hidden. Else it can happen that the last frame of a previous menu is still
// visible when the new menu is shown. For now, I have not seen any issues with
// background throttling disabled.
backgroundThrottling: false,
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
},
transparent: true,
Expand Down Expand Up @@ -808,7 +815,7 @@ export class KandoApp {
// Also wait with the execution of the selected action until the fade-out
// animation is finished to make sure that any resulting events (such as virtual
// key presses) are not captured by the window.
this.hideWindow(400).then(() => {
this.hideWindow().then(() => {
// If the action is delayed, we execute it after the window is hidden.
if (executeDelayed) {
execute(item);
Expand All @@ -819,7 +826,7 @@ export class KandoApp {
// We do not hide the window immediately when the user aborts a selection. Instead, we
// wait for the fade-out animation to finish.
ipcMain.on('cancel-selection', () => {
this.hideWindow(300);
this.hideWindow();
});
}

Expand Down Expand Up @@ -1011,7 +1018,7 @@ export class KandoApp {
*
* See also: https://stackoverflow.com/questions/50642126/previous-window-focus-electron
*/
private async hideWindow(delay = 0) {
private async hideWindow() {
return new Promise<void>((resolve) => {
if (this.hideTimeout) {
clearTimeout(this.hideTimeout);
Expand All @@ -1032,7 +1039,7 @@ export class KandoApp {
this.hideTimeout = null;

resolve();
}, delay);
}, this.appSettings.get().fadeOutDuration);
});
}

Expand Down
17 changes: 15 additions & 2 deletions src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ Promise.all([
window.api.getBackendInfo(),
window.api.getMenuTheme(),
window.api.getCurrentMenuThemeColors(),
]).then(async ([locales, info, themeDescription, colors]) => {
window.api.appSettings.get(),
]).then(async ([locales, info, themeDescription, colors, settings]) => {
// Initialize i18next with the current locale and the english fallback locale.
await i18next.init({
lng: locales.current,
Expand Down Expand Up @@ -72,7 +73,10 @@ Promise.all([

// Now, we create a new menu and a new editor. The menu is responsible for rendering
// the menu items and the editor is responsible for rendering the editor UI.
const menu = new Menu(document.getElementById('kando-menu'), menuTheme);
const menu = new Menu(document.getElementById('kando-menu'), menuTheme, {
fadeInDuration: settings.fadeInDuration,
fadeOutDuration: settings.fadeOutDuration,
});
const editor = new Editor(document.getElementById('kando-editor'), info);

// Show the menu when the main process requests it.
Expand All @@ -98,6 +102,15 @@ Promise.all([
document.getElementById('sidebar-show-new-version-button').classList.remove('d-none');
});

// Tell the menu about the current fade durations.
window.api.appSettings.onChange('fadeInDuration', (fadeInDuration) => {
menu.setFadeInDuration(fadeInDuration);
});

window.api.appSettings.onChange('fadeOutDuration', (fadeOutDuration) => {
menu.setFadeOutDuration(fadeOutDuration);
});

// Sometimes, the user may select an item too close to the edge of the screen. In this
// case, we can not open the menu directly under the pointer. To make sure that the
// menu is still exactly under the pointer, we move the pointer a little bit.
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/menu/menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@
// SPDX-License-Identifier: MIT

#kando-menu {
transition: opacity 150ms ease;
transition: opacity var(--fade-in-duration) ease;

// When the menu is hidden or shown, we fade it to / from transparent.
&.hidden {
transition: opacity var(--fade-out-duration) ease;
opacity: 0;

// We also want to delay the fade-out animation if a node is selected. Else the
// selected node would disappear before the position transition is finished.
&.selected {
transition-delay: 150ms;
transition: opacity calc(var(--fade-out-duration) * 0.5) ease;
transition-delay: calc(var(--fade-out-duration) * 0.5);
}
}

Expand Down
Loading

0 comments on commit 9054780

Please sign in to comment.