mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Refactor and transform "Application update", "Preferences" and "Application menu" into Features (#6437)
* Move some code for application update to feature directory The rest of the code could not be moved yet because of work-in-progress refactorings for OCP compliance. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce helper to get a global override for a function-injectable Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract global override-files from bloated getDiForUnitTesting Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Move some more code for application update to feature directory Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce competition for top bar items to achieve OCP-compliance Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract top menu item for opening context menu using the new competition Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract top menu item for navigating to home as OCP Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract top menu item for navigating to back as OCP Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract top menu item for navigating to forward as OCP Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract top menu item for application update as OCP Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Format code to make ongoing refactoring a bit easier Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Add missing unit tests for top bar extendability using extension API This makes ongoing refactoring easier. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Replace implementation for old top-bar items for losing competition Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract top menu item for window controls as OCP Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce reusable component for spacing between other components Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce helper component to render list of React elements Features: - Placeholder for empty list - Separators between items - No boilerplate for "key" prop in React Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix double-clicking and dragging of window from top bar Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update snapshots Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix stuff broken in rebase Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Update snapshots after rebase Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make fake time have a default value for "now" Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Migrate some application menu items to injectables Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate separators of application menu in single file Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Remove duplication from separators in application menu Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract some operation system actions from application menu as injectables Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract menu item for quitting application as injectable Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce way to type narrow a string property Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make the di's for unit testing able to auto-register also named exports Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make global override less strict to simplify setup of many unit tests There's a better solution for this in the horizon, as this overridden thing is better faked than stubbed. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify a test Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce way to create hierarchical composites from a flat array Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Implement hierarchy of application menu items using "many-root" composite Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Migrate more application menu items to injectables Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Simplify hierarchy of application menu items using "single-root" composite Also solve composed typing of application menu by using Discriminated Unions of TypeScript, see: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update snapshot Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify creation of composite Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make composite able to have custom handler for missing parent ids This will be useful next for application menu items, where a missing parent id cannot be fatal. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Defend against self-referencing composites Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Reintroduce non-fatal handling of orphan application menu items Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make faked, yet weak, typing a bit stronger Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify getting of composite paths Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make registrator for application menu items support all known scenarios Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Add logging for unrecognizable application menu item types Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Rename id of menu item to keep it discoverable by existing extensions Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate code to check for updates closer to feature Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Introduce reusable horizontal line Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for preferences as a Feature Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for terminal preference tab Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for editor preference tab Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for proxy preference tab Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for telemetry preference tab Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for application preference tab Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Move code related to helm chart preferences under related Feature in preparation for competition Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for kubernetes preference tab Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using competition for application preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using competition for editor preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using competition for kubernetes preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using competition for proxy preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add missing observer to make sure component updates Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using competition for telemetry preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Switch to using competition for terminal preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak UI for preferences Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove dead code Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Tweak more UI of preferences Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Revert "Introduce reusable horizontal line" This reverts commit 4d8c147fe0f1a14bd884f73cf345e7d3a28b954a. Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove dead code Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce utility to find exactly one item from array Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce competition for preferences navigation Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Move code under a Feature Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove usage of old code Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove dead code Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add extensions tab group to preferences Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce way to find out if composite has a descendant This will serve eg. hiding of empty preference tab groups. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make tab groups and tabs in preferences not render when there is no content Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Remove code made redundant with hiding of preference tabs without content Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Tweak UI for preference navigation tab groups Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce test helper to abstract discovery of HTML elements Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Kill dead code Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate discovery of HTML elements in some tests Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update snapshots Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt application builder to changes in preference navigation Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt test setup to changes in preference navigation Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove uninteresting technical tests that are covered by behavioural ones Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate discovery of HTML elements in a test Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove test ID made redundant by consolidating discovery of HTML elements Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove duplication from preference pages Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix import Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make queries in element discovery return matching attribute values for easier testing Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make element discovery able to do nested discovery Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make element discovery able to discover without value for attribute Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Implement registrator for preference items Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update snapshots Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make styling less brittle by not relying on static HTML-element structures with CSS-rules Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Add todo Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Remove "group" from preference types, as it is exact replica of "item" Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Update snapshots Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Replace usages of react-component factory with actual components for simplicity Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Start considering application preferences as default tab Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate naming Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make sense in horizontal lines Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Clean public interface of a normalize composite Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate name of function Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate directory structure of composite Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Move utility functions to common Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Rename a preference item type to better communicate intent in UI Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Move shared UI component to more common place Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate sizing of horizontal line to t-shirts Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Move application update related preferences under application update feature Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make winner of competition to use original route for preferences Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make HTML element discovery require less parameters Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Extract "composable-responsibilities" for Discriminable, Labelable, Orderable, and Showable Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Update snapshot Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Remove dead code Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Move code under a feature Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate navigating to preferences Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Move code under a feature Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Relocate code under a sub-feature Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add TODO Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove dead code Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix merge conflicts Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update snapshots after rebase Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix import path after rebase Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove duplication from exhaustiveness checks for discriminating unions Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Add TODO Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Update link to a more recent article Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify static Showability of a PreferenceItem Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Move general function to general directory Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract responsibility of "separability" Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make separator in Map-component know left and right item Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Remove additional separators when separated items are not shown for having no content Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Update snapshots Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix lint error Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt integration test to recent changes Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt more integration tests to recent changes Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make composite not care about in formatting of ids Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Adapt application builder and tests to array-like paths over string-like paths Array-like paths do not have weakness for special characters as part of id, such as ".". Also note: the error messaging for clicking of application menu in application builder is a bit worse now I think, but the simplification of the test code is worth it in this case IMHO. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make composite not care about formatting of ids Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Adapt application builder and tests to array-like paths over string-like paths Array-like paths do not have weakness for special characters as part of id, such as ".". Also note: the error messaging for clicking of application menu in application builder is a bit worse now I think, but the simplification of the test code is worth it in this case IMHO. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate output of get-composite-path to match find-composite's input Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make global overrides for functions log args of the call for devability Also make the thrown error suggest how to fix the problem. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make attempts to log error throw in unit tests Errors cannot be allowed to happen without a unit test explicitly causing it. Errors cannot be allowed to happen without author of unit test knowing it. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make composite not know about how children are transformed Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Remove some duplication from tests of composite Also make the thrown error suggest how to fix the problem. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make composite unit test an unrealistic test scenario about undefined ids Also make the thrown error suggest how to fix the problem. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Kill dead code Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify unit tests for composite Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate tests to now point-free composite Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify "Showable" Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make non-shown application menu items not break composite structure This was made apparent by adding related unit tests for all known environments. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify usages of Orderable and Showable Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Extract being maybe Showable as explicit composable responsibility Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make more showables maybe showable Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate logic for application menu for Windows to be based on composite Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Start using named export for composite Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Rename type for accuracy Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Remove unnecessary type and value Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make composable responsibilities readonly to nudge towards immutability Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Remove a bit of duplication to create TS-constants Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Make a comment and test name make more sense Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify fallthrough in a switch/case Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Replace inline styles with proper CSS Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Switch to correct type to indicate "object which might not contain a property" Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Simplify overriding of platform in a unit test Also make typing of platforms more strict, and remove some magic strings. Also add a TODO for further OCP-ification. Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Consolidate some "maybe-types" and arguments using them Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> * Update snapshots Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
1 parent
38feab813c
commit
37eb236948
418 files changed
+39647
-27024
No files matched your search
@@ -12,43 +12,61 @@ exports[`installing update when started renders 1`] = `
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -214,43 +232,61 @@ exports[`installing update when started when user checks for updates renders 1`]
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -416,43 +452,61 @@ exports[`installing update when started when user checks for updates when new up
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -618,61 +672,83 @@ exports[`installing update when started when user checks for updates when new up
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
data-icon-name="home"
|
||||
>
|
||||
arrow_drop_down
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
>
|
||||
arrow_drop_down
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -838,61 +914,83 @@ exports[`installing update when started when user checks for updates when new up
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
data-icon-name="home"
|
||||
>
|
||||
arrow_drop_down
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
>
|
||||
arrow_drop_down
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -1058,43 +1156,61 @@ exports[`installing update when started when user checks for updates when no new
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import publishIsConfiguredInjectable from "./main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { CheckForPlatformUpdates } from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import type { CheckForPlatformUpdates } from "./main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "./main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import appEventBusInjectable from "../../common/app-event-bus/app-event-bus.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||
import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable";
|
||||
import processCheckingForUpdatesInjectable from "./main/process-checking-for-updates.injectable";
|
||||
import type { DownloadPlatformUpdate } from "./main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "./main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import quitAndInstallUpdateInjectable from "./main/quit-and-install-update.injectable";
|
||||
import periodicalCheckForUpdatesInjectable from "./child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
import emitEventInjectable from "../../common/app-event-bus/emit-event.injectable";
|
||||
import getBuildVersionInjectable from "../../main/vars/build-version/get-build-version.injectable";
|
||||
@@ -142,7 +142,7 @@ describe("analytics for installing update", () => {
|
||||
it("when checking for updates using application menu, sends event to analytics for being checked from application menu", async () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
builder.applicationMenu.click("root.check-for-updates");
|
||||
builder.applicationMenu.click("root", "mac", "check-for-updates");
|
||||
|
||||
expect(analyticsListenerMock.mock.calls).toEqual([
|
||||
[
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
|
||||
import applicationMenuItemInjectionToken from "../../../../application-menu/main/menu-items/application-menu-item-injection-token";
|
||||
import processCheckingForUpdatesInjectable from "../../../main/process-checking-for-updates.injectable";
|
||||
import showApplicationWindowInjectable from "../../../../../main/start-main-application/lens-window/show-application-window.injectable";
|
||||
import updatingIsEnabledInjectable from "../../../main/updating-is-enabled/updating-is-enabled.injectable";
|
||||
import isMacInjectable from "../../../../../common/vars/is-mac.injectable";
|
||||
|
||||
const checkForUpdatesMenuItemInjectable = getInjectable({
|
||||
id: "check-for-updates-menu-item",
|
||||
|
||||
instantiate: (di) => {
|
||||
const processCheckingForUpdates = di.inject(
|
||||
processCheckingForUpdatesInjectable,
|
||||
);
|
||||
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
|
||||
const updatingIsEnabled = di.inject(updatingIsEnabledInjectable);
|
||||
const isMac = di.inject(isMacInjectable);
|
||||
|
||||
return {
|
||||
kind: "clickable-menu-item" as const,
|
||||
id: "check-for-updates",
|
||||
parentId: isMac ? "mac" : "help",
|
||||
orderNumber: isMac ? 20 : 50,
|
||||
label: "Check for updates",
|
||||
isShown: updatingIsEnabled,
|
||||
|
||||
onClick: () => {
|
||||
// Todo: implement using async/await
|
||||
processCheckingForUpdates("application-menu").then(() =>
|
||||
showApplicationWindow(),
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: applicationMenuItemInjectionToken,
|
||||
});
|
||||
|
||||
export default checkForUpdatesMenuItemInjectable;
|
||||
+116
-76
@@ -12,61 +12,83 @@ exports[`encourage user to update when sufficient time passed since update was d
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
data-icon-name="home"
|
||||
>
|
||||
arrow_drop_down
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
>
|
||||
arrow_drop_down
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -232,43 +254,61 @@ exports[`encourage user to update when sufficient time passed since update was d
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
+11
-11
@@ -6,17 +6,17 @@ import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { act } from "@testing-library/react";
|
||||
import type { CheckForPlatformUpdates } from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
import type { CheckForPlatformUpdates } from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import type { DownloadPlatformUpdate } from "../../main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable";
|
||||
import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import processCheckingForUpdatesInjectable from "../../main/process-checking-for-updates.injectable";
|
||||
import quitAndInstallUpdateInjectable from "../../main/quit-and-install-update.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../../../common/test-utils/use-fake-time";
|
||||
|
||||
function daysToMilliseconds(days: number) {
|
||||
return Math.round(days * 24 * 60 * 60 * 1000);
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import { topBarItemOnRightSideInjectionToken } from "../../../../../../renderer/components/layout/top-bar/top-bar-items/top-bar-item-injection-token";
|
||||
import { UpdateButton } from "./update-button";
|
||||
import updateWarningLevelInjectable from "./update-warning-level.injectable";
|
||||
|
||||
const updateApplicationTopBarItemInjectable = getInjectable({
|
||||
id: "update-application-top-bar-item",
|
||||
|
||||
instantiate: (di) => {
|
||||
const warningLevel = di.inject(updateWarningLevelInjectable);
|
||||
|
||||
return {
|
||||
id: "update-application",
|
||||
isShown: computed(() => !!warningLevel.get()),
|
||||
orderNumber: 50,
|
||||
Component: UpdateButton,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: topBarItemOnRightSideInjectionToken,
|
||||
});
|
||||
|
||||
export default updateApplicationTopBarItemInjectable;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
export * from "./update-button";
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
.updateButton {
|
||||
--accent-color: var(--colorOk);
|
||||
|
||||
border: 1px solid var(--accent-color);
|
||||
border-radius: 4px;
|
||||
color: var(--accent-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: calc(var(--padding) / 4) var(--padding);
|
||||
gap: 6px;
|
||||
cursor: default;
|
||||
position: relative;
|
||||
|
||||
&:hover::before{
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--blue);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
background: var(--accent-color);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
opacity: 0.15;
|
||||
z-index: -1;
|
||||
transition: opacity 0.1s;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.warningMedium {
|
||||
--accent-color: var(--colorWarning);
|
||||
}
|
||||
|
||||
.warningHigh {
|
||||
--accent-color: var(--colorSoftError);
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import styles from "./styles.module.scss";
|
||||
|
||||
import type { HTMLAttributes } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { Menu, MenuItem } from "../../../../../../../renderer/components/menu";
|
||||
import { cssNames } from "../../../../../../../renderer/utils";
|
||||
import type { IconProps } from "../../../../../../../renderer/components/icon";
|
||||
import { Icon } from "../../../../../../../renderer/components/icon";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import restartAndInstallUpdateInjectable from "../../../../../renderer/restart-and-install-update.injectable";
|
||||
import updateWarningLevelInjectable from "../update-warning-level.injectable";
|
||||
|
||||
interface UpdateButtonProps extends HTMLAttributes<HTMLButtonElement> {}
|
||||
|
||||
interface Dependencies {
|
||||
warningLevel: IComputedValue<"light" | "medium" | "high" | "">;
|
||||
update: () => void;
|
||||
}
|
||||
|
||||
export const NonInjectedUpdateButton = observer(({ warningLevel, update, id }: UpdateButtonProps & Dependencies) => {
|
||||
const buttonId = id ?? "update-lens-button";
|
||||
const menuIconProps: IconProps = { material: "update", small: true };
|
||||
const [opened, setOpened] = useState(false);
|
||||
const level = warningLevel.get();
|
||||
|
||||
const toggle = () => {
|
||||
setOpened(!opened);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
data-testid="update-button"
|
||||
data-warning-level={level}
|
||||
id={buttonId}
|
||||
className={cssNames(styles.updateButton, {
|
||||
[styles.warningHigh]: level === "high",
|
||||
[styles.warningMedium]: level === "medium",
|
||||
})}
|
||||
>
|
||||
Update
|
||||
<Icon material="arrow_drop_down" className={styles.icon}/>
|
||||
</button>
|
||||
<Menu
|
||||
usePortal
|
||||
htmlFor={buttonId}
|
||||
isOpen={opened}
|
||||
close={toggle}
|
||||
open={toggle}
|
||||
>
|
||||
<MenuItem
|
||||
icon={menuIconProps}
|
||||
onClick={update}
|
||||
data-testid="update-lens-menu-item"
|
||||
>
|
||||
Relaunch to Update Lens
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export const UpdateButton = withInjectables<Dependencies, UpdateButtonProps>(
|
||||
NonInjectedUpdateButton,
|
||||
{
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
warningLevel: di.inject(updateWarningLevelInjectable),
|
||||
update: di.inject(restartAndInstallUpdateInjectable),
|
||||
}),
|
||||
},
|
||||
);
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import updateDownloadedDateTimeInjectable from "../../../../common/update-downloaded-date-time/update-downloaded-date-time.injectable";
|
||||
import { reactiveNow } from "../../../../../../common/utils/reactive-now/reactive-now";
|
||||
|
||||
const updateWarningLevelInjectable = getInjectable({
|
||||
id: "update-warning-level",
|
||||
|
||||
instantiate: (di) => {
|
||||
const updateDownloadedDateTime = di.inject(updateDownloadedDateTimeInjectable);
|
||||
|
||||
return computed(() => {
|
||||
const downloadedAt = updateDownloadedDateTime.value.get();
|
||||
|
||||
if (!downloadedAt) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const ONE_DAY = 1000 * 60 * 60 * 24;
|
||||
|
||||
const downloadedAtTimestamp = new Date(downloadedAt).getTime();
|
||||
const currentDateTimeTimestamp = reactiveNow(ONE_DAY);
|
||||
|
||||
const elapsedTime = currentDateTimeTimestamp - downloadedAtTimestamp;
|
||||
|
||||
const elapsedDays = elapsedTime / ONE_DAY;
|
||||
|
||||
if (elapsedDays < 20) {
|
||||
return "light";
|
||||
}
|
||||
|
||||
if (elapsedDays >= 20 && elapsedDays < 25) {
|
||||
return "medium";
|
||||
}
|
||||
|
||||
return "high";
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default updateWarningLevelInjectable;
|
||||
+328
-212
@@ -12,43 +12,61 @@ exports[`installing update using tray when started renders 1`] = `
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -214,43 +232,61 @@ exports[`installing update using tray when started when user checks for updates
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -416,43 +452,61 @@ exports[`installing update using tray when started when user checks for updates
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -618,61 +672,83 @@ exports[`installing update using tray when started when user checks for updates
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
data-icon-name="home"
|
||||
>
|
||||
arrow_drop_down
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
>
|
||||
arrow_drop_down
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -838,61 +914,83 @@ exports[`installing update using tray when started when user checks for updates
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
data-icon-name="home"
|
||||
>
|
||||
arrow_drop_down
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
>
|
||||
arrow_drop_down
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -1058,43 +1156,61 @@ exports[`installing update using tray when started when user checks for updates
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
+10
-10
@@ -2,19 +2,19 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import type { CheckForPlatformUpdates } from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable";
|
||||
import type { CheckForPlatformUpdates } from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/get-current-application-window.injectable";
|
||||
import type { DownloadPlatformUpdate } from "../../main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import type { LensWindow } from "../../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "../../../../main/start-main-application/lens-window/application-window/get-current-application-window.injectable";
|
||||
|
||||
describe("installing update using tray", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import getTrayIconPathInjectable from "../../../../../../main/tray/menu-icon/get-tray-icon-path.injectable";
|
||||
import { trayIconInjectionToken } from "../../../../../../main/tray/menu-icon/tray-icon-injection-token";
|
||||
import updatesAreBeingDiscoveredInjectable from "../../../../common/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||
import updateIsBeingDownloadedInjectable from "../../../../common/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||
|
||||
const checkingForUpdatesTrayIconInjectable = getInjectable({
|
||||
id: "checking-for-updates-tray-icon",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getTrayIconPath = di.inject(getTrayIconPathInjectable);
|
||||
const updatesAreBeingDiscovered = di.inject(updatesAreBeingDiscoveredInjectable);
|
||||
const updateIsBeingDownloaded = di.inject(updateIsBeingDownloadedInjectable);
|
||||
|
||||
return {
|
||||
iconPath: getTrayIconPath("checking-for-updates"),
|
||||
priority: 1,
|
||||
shouldBeShown: computed(
|
||||
() =>
|
||||
updatesAreBeingDiscovered.value.get() ||
|
||||
updateIsBeingDownloaded.value.get(),
|
||||
),
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: trayIconInjectionToken,
|
||||
});
|
||||
|
||||
export default checkingForUpdatesTrayIconInjectable;
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import getTrayIconPathInjectable from "../../../../../../main/tray/menu-icon/get-tray-icon-path.injectable";
|
||||
import { trayIconInjectionToken } from "../../../../../../main/tray/menu-icon/tray-icon-injection-token";
|
||||
import updateIsReadyToBeInstalledInjectable from "../update-is-ready-to-be-installed.injectable";
|
||||
|
||||
const updateIsReadyToBeInstalledTrayIconInjectable = getInjectable({
|
||||
id: "update-is-ready-to-be-installed-tray-icon",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getTrayIconPath = di.inject(getTrayIconPathInjectable);
|
||||
const updateIsReadyToBeInstalled = di.inject(updateIsReadyToBeInstalledInjectable);
|
||||
|
||||
return {
|
||||
iconPath: getTrayIconPath("update-available"),
|
||||
priority: 1,
|
||||
shouldBeShown: updateIsReadyToBeInstalled,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: trayIconInjectionToken,
|
||||
});
|
||||
|
||||
export default updateIsReadyToBeInstalledTrayIconInjectable;
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import updatingIsEnabledInjectable from "../../../../main/updating-is-enabled/updating-is-enabled.injectable";
|
||||
import { trayMenuItemInjectionToken } from "../../../../../../main/tray/tray-menu-item/tray-menu-item-injection-token";
|
||||
import showApplicationWindowInjectable from "../../../../../../main/start-main-application/lens-window/show-application-window.injectable";
|
||||
import discoveredUpdateVersionInjectable from "../../../../common/discovered-update-version/discovered-update-version.injectable";
|
||||
import updateIsBeingDownloadedInjectable from "../../../../common/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||
import updatesAreBeingDiscoveredInjectable from "../../../../common/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||
import progressOfUpdateDownloadInjectable from "../../../../common/progress-of-update-download/progress-of-update-download.injectable";
|
||||
import assert from "assert";
|
||||
import processCheckingForUpdatesInjectable from "../../../../main/process-checking-for-updates.injectable";
|
||||
import { withErrorSuppression } from "../../../../../../common/utils/with-error-suppression/with-error-suppression";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import withErrorLoggingInjectable from "../../../../../../common/utils/with-error-logging/with-error-logging.injectable";
|
||||
|
||||
const checkForUpdatesTrayItemInjectable = getInjectable({
|
||||
id: "check-for-updates-tray-item",
|
||||
|
||||
instantiate: (di) => {
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
const updatingIsEnabled = di.inject(updatingIsEnabledInjectable);
|
||||
const progressOfUpdateDownload = di.inject(progressOfUpdateDownloadInjectable);
|
||||
const discoveredVersionState = di.inject(discoveredUpdateVersionInjectable);
|
||||
const downloadingUpdateState = di.inject(updateIsBeingDownloadedInjectable);
|
||||
const checkingForUpdatesState = di.inject(updatesAreBeingDiscoveredInjectable);
|
||||
const processCheckingForUpdates = di.inject(processCheckingForUpdatesInjectable);
|
||||
const withErrorLoggingFor = di.inject(withErrorLoggingInjectable);
|
||||
|
||||
return {
|
||||
id: "check-for-updates",
|
||||
parentId: null,
|
||||
orderNumber: 30,
|
||||
|
||||
label: computed(() => {
|
||||
if (downloadingUpdateState.value.get()) {
|
||||
const discoveredVersion = discoveredVersionState.value.get();
|
||||
|
||||
assert(discoveredVersion);
|
||||
|
||||
const roundedPercentage = Math.round(progressOfUpdateDownload.value.get().percentage);
|
||||
|
||||
return `Downloading update ${discoveredVersion.version} (${roundedPercentage}%)...`;
|
||||
}
|
||||
|
||||
if (checkingForUpdatesState.value.get()) {
|
||||
return "Checking for updates...";
|
||||
}
|
||||
|
||||
return "Check for updates";
|
||||
}),
|
||||
|
||||
enabled: computed(() => !checkingForUpdatesState.value.get() && !downloadingUpdateState.value.get()),
|
||||
|
||||
visible: computed(() => updatingIsEnabled),
|
||||
|
||||
click: pipeline(
|
||||
async () => {
|
||||
const { updateIsReadyToBeInstalled } = await processCheckingForUpdates("tray");
|
||||
|
||||
if (updateIsReadyToBeInstalled) {
|
||||
await showApplicationWindow();
|
||||
}
|
||||
},
|
||||
|
||||
withErrorLoggingFor(() => "[TRAY]: Checking for updates failed."),
|
||||
|
||||
// TODO: Find out how to improve typing so that instead of
|
||||
// x => withErrorSuppression(x) there could only be withErrorSuppression
|
||||
(x) => withErrorSuppression(x),
|
||||
),
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: trayMenuItemInjectionToken,
|
||||
});
|
||||
|
||||
export default checkForUpdatesTrayItemInjectable;
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import { trayMenuItemInjectionToken } from "../../../../../../main/tray/tray-menu-item/tray-menu-item-injection-token";
|
||||
import discoveredUpdateVersionInjectable from "../../../../common/discovered-update-version/discovered-update-version.injectable";
|
||||
import { withErrorSuppression } from "../../../../../../common/utils/with-error-suppression/with-error-suppression";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import withErrorLoggingInjectable from "../../../../../../common/utils/with-error-logging/with-error-logging.injectable";
|
||||
import quitAndInstallUpdateInjectable from "../../../../main/quit-and-install-update.injectable";
|
||||
import updateIsReadyToBeInstalledInjectable from "../update-is-ready-to-be-installed.injectable";
|
||||
|
||||
const installApplicationUpdateTrayItemInjectable = getInjectable({
|
||||
id: "install-update-tray-item",
|
||||
|
||||
instantiate: (di) => {
|
||||
const quitAndInstallUpdate = di.inject(quitAndInstallUpdateInjectable);
|
||||
const discoveredVersionState = di.inject(discoveredUpdateVersionInjectable);
|
||||
const withErrorLoggingFor = di.inject(withErrorLoggingInjectable);
|
||||
const updateIsReadyToBeInstalled = di.inject(updateIsReadyToBeInstalledInjectable);
|
||||
|
||||
return {
|
||||
id: "install-update",
|
||||
parentId: null,
|
||||
orderNumber: 50,
|
||||
|
||||
label: computed(() => {
|
||||
const versionToBeInstalled = discoveredVersionState.value.get()?.version;
|
||||
|
||||
return `Install update ${versionToBeInstalled}`;
|
||||
}),
|
||||
|
||||
enabled: computed(() => true),
|
||||
|
||||
visible: updateIsReadyToBeInstalled,
|
||||
|
||||
click: pipeline(
|
||||
quitAndInstallUpdate,
|
||||
|
||||
withErrorLoggingFor(() => "[TRAY]: Update installation failed."),
|
||||
|
||||
// TODO: Find out how to improve typing so that instead of
|
||||
// x => withErrorSuppression(x) there could only be withErrorSuppression
|
||||
(x) => withErrorSuppression(x),
|
||||
),
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: trayMenuItemInjectionToken,
|
||||
});
|
||||
|
||||
export default installApplicationUpdateTrayItemInjectable;
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import discoveredUpdateVersionInjectable from "../../../common/discovered-update-version/discovered-update-version.injectable";
|
||||
import updateIsBeingDownloadedInjectable from "../../../common/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||
|
||||
const updateIsReadyToBeInstalledInjectable = getInjectable({
|
||||
id: "update-is-ready-to-be-installed",
|
||||
|
||||
instantiate: (di) => {
|
||||
const discoveredUpdateVersion = di.inject(discoveredUpdateVersionInjectable);
|
||||
const updateIsBeingDownloaded = di.inject(updateIsBeingDownloadedInjectable);
|
||||
|
||||
return computed(
|
||||
() =>
|
||||
!!discoveredUpdateVersion.value.get() &&
|
||||
!updateIsBeingDownloaded.value.get(),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export default updateIsReadyToBeInstalledInjectable;
|
||||
+204
-138
@@ -12,61 +12,83 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
data-icon-name="home"
|
||||
>
|
||||
arrow_drop_down
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
>
|
||||
arrow_drop_down
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -232,61 +254,83 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
data-icon-name="home"
|
||||
>
|
||||
arrow_drop_down
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
>
|
||||
arrow_drop_down
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
@@ -499,61 +543,83 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
data-icon-name="home"
|
||||
>
|
||||
arrow_drop_down
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<button
|
||||
class="updateButton"
|
||||
data-testid="update-button"
|
||||
data-warning-level="light"
|
||||
id="update-lens-button"
|
||||
>
|
||||
Update
|
||||
<i
|
||||
class="Icon icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_drop_down"
|
||||
>
|
||||
arrow_drop_down
|
||||
</span>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
+12
-12
@@ -2,23 +2,23 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { CheckForPlatformUpdates } from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { CheckForPlatformUpdates } from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import type { DownloadPlatformUpdate } from "../../main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/process-checking-for-updates.injectable";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { fireEvent } from "@testing-library/react";
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||
import timeAfterUpdateMustBeInstalledInjectable from "../../renderer/application-update/force-update-modal/time-after-update-must-be-installed.injectable";
|
||||
import secondsAfterInstallStartsInjectable from "../../renderer/application-update/force-update-modal/seconds-after-install-starts.injectable";
|
||||
import forceUpdateModalRootFrameComponentInjectable from "../../renderer/application-update/force-update-modal/force-update-modal-root-frame-component.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../../../common/test-utils/use-fake-time";
|
||||
import quitAndInstallUpdateInjectable from "../../main/quit-and-install-update.injectable";
|
||||
import timeAfterUpdateMustBeInstalledInjectable from "./renderer/force-update-modal/time-after-update-must-be-installed.injectable";
|
||||
import secondsAfterInstallStartsInjectable from "./renderer/force-update-modal/seconds-after-install-starts.injectable";
|
||||
import forceUpdateModalRootFrameComponentInjectable from "./renderer/force-update-modal/force-update-modal-root-frame-component.injectable";
|
||||
|
||||
const TIME_AFTER_UPDATE_MUST_BE_INSTALLED = 1000;
|
||||
const TIME_AFTER_INSTALL_STARTS = 5 * 1000;
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { computed } from "mobx";
|
||||
import { getGlobalOverride } from "../../../../../../common/test-utils/get-global-override";
|
||||
import forceUpdateModalRootFrameComponentInjectable from "./force-update-modal-root-frame-component.injectable";
|
||||
|
||||
export default getGlobalOverride(
|
||||
forceUpdateModalRootFrameComponentInjectable,
|
||||
|
||||
() => ({
|
||||
id: "force-update-modal",
|
||||
Component: () => null,
|
||||
shouldRender: computed(() => false),
|
||||
}),
|
||||
);
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import { rootFrameChildComponentInjectionToken } from "../../../../../../renderer/frames/root-frame/root-frame-child-component-injection-token";
|
||||
import { ForceUpdateModal } from "./force-update-modal";
|
||||
import timeSinceUpdateWasDownloadedInjectable from "./time-since-update-was-downloaded.injectable";
|
||||
import updateDownloadedDateTimeInjectable from "../../../../common/update-downloaded-date-time/update-downloaded-date-time.injectable";
|
||||
import timeAfterUpdateMustBeInstalledInjectable from "./time-after-update-must-be-installed.injectable";
|
||||
|
||||
const forceUpdateModalRootFrameComponentInjectable = getInjectable({
|
||||
id: "force-update-modal-root-frame-component",
|
||||
|
||||
instantiate: (di) => {
|
||||
const timeSinceUpdateWasDownloaded = di.inject(timeSinceUpdateWasDownloadedInjectable);
|
||||
const updateDownloadedDateTime = di.inject(updateDownloadedDateTimeInjectable);
|
||||
const timeWhenUpdateMustBeInstalled = di.inject(timeAfterUpdateMustBeInstalledInjectable);
|
||||
|
||||
return {
|
||||
id: "force-update-modal",
|
||||
Component: ForceUpdateModal,
|
||||
|
||||
shouldRender: computed(
|
||||
() =>
|
||||
!!updateDownloadedDateTime.value.get() &&
|
||||
timeSinceUpdateWasDownloaded.get() >= timeWhenUpdateMustBeInstalled,
|
||||
),
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: rootFrameChildComponentInjectionToken,
|
||||
|
||||
// Note: Globally overridden because it observes the current time which can cause long running tests
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default forceUpdateModalRootFrameComponentInjectable;
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
$baseline: 8px;
|
||||
|
||||
.ForceUpdateModal {
|
||||
background-color: white;
|
||||
border-radius: 1 * $baseline;
|
||||
padding: 3 * $baseline;
|
||||
width: 50 * $baseline;
|
||||
|
||||
.header {
|
||||
margin-bottom: 2 * $baseline;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 2 * $baseline;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import React from "react";
|
||||
import restartAndInstallUpdateInjectable from "../../../../renderer/restart-and-install-update.injectable";
|
||||
import { Countdown } from "../../../../../../renderer/components/countdown/countdown";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import installUpdateCountdownInjectable from "./install-update-countdown.injectable";
|
||||
import { Dialog } from "../../../../../../renderer/components/dialog";
|
||||
import { Button } from "../../../../../../renderer/components/button";
|
||||
import styles from "./force-update-modal.module.scss";
|
||||
|
||||
interface Dependencies {
|
||||
restartAndInstallUpdate: () => void;
|
||||
secondsTill: IComputedValue<number>;
|
||||
}
|
||||
|
||||
const NonInjectedForceUpdateModal = observer(
|
||||
({ restartAndInstallUpdate, secondsTill }: Dependencies) => (
|
||||
<Dialog isOpen={true} pinned>
|
||||
<div
|
||||
data-testid="must-update-immediately"
|
||||
className={styles.ForceUpdateModal}
|
||||
>
|
||||
<div className={styles.header}>
|
||||
<h2>Please update</h2>
|
||||
</div>
|
||||
|
||||
<div className={styles.content}>
|
||||
<p>
|
||||
An update to Lens Desktop is required to continue using the application.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.footer}>
|
||||
<Button
|
||||
primary
|
||||
data-testid="update-now-from-must-update-immediately-modal"
|
||||
onClick={restartAndInstallUpdate}
|
||||
label="Update"
|
||||
>
|
||||
{" "}
|
||||
(
|
||||
<Countdown
|
||||
secondsTill={secondsTill}
|
||||
data-testid="countdown-to-automatic-update"
|
||||
/>
|
||||
)
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
),
|
||||
);
|
||||
|
||||
export const ForceUpdateModal = withInjectables<Dependencies>(
|
||||
NonInjectedForceUpdateModal,
|
||||
|
||||
{
|
||||
getProps: (di, props) => ({
|
||||
restartAndInstallUpdate: di.inject(restartAndInstallUpdateInjectable),
|
||||
secondsTill: di.inject(installUpdateCountdownInjectable),
|
||||
...props,
|
||||
}),
|
||||
},
|
||||
);
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import countdownStateInjectable from "../../../../../../renderer/components/countdown/countdown-state.injectable";
|
||||
import secondsAfterInstallStartsInjectable from "./seconds-after-install-starts.injectable";
|
||||
import restartAndInstallUpdateInjectable from "../../../../renderer/restart-and-install-update.injectable";
|
||||
|
||||
const installUpdateCountdownInjectable = getInjectable({
|
||||
id: "install-update-countdown",
|
||||
|
||||
instantiate: (di) => {
|
||||
const secondsAfterInstallStarts = di.inject(secondsAfterInstallStartsInjectable);
|
||||
const restartAndInstallUpdate = di.inject(restartAndInstallUpdateInjectable);
|
||||
|
||||
return di.inject(countdownStateInjectable, {
|
||||
startFrom: secondsAfterInstallStarts,
|
||||
|
||||
onZero: () => {
|
||||
restartAndInstallUpdate();
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default installUpdateCountdownInjectable;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
|
||||
const secondsAfterInstallStartsInjectable = getInjectable({
|
||||
id: "seconds-after-install-starts",
|
||||
instantiate: () => 90,
|
||||
});
|
||||
|
||||
export default secondsAfterInstallStartsInjectable;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
|
||||
const THIRTY_DAYS = 30 * 24 * 60 * 60 * 1000;
|
||||
|
||||
const timeAfterUpdateMustBeInstalledInjectable = getInjectable({
|
||||
id: "time-after-update-must-be-installed",
|
||||
instantiate: () => THIRTY_DAYS,
|
||||
});
|
||||
|
||||
export default timeAfterUpdateMustBeInstalledInjectable;
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { computed } from "mobx";
|
||||
import moment from "moment";
|
||||
import updateDownloadedDateTimeInjectable from "../../../../common/update-downloaded-date-time/update-downloaded-date-time.injectable";
|
||||
import { reactiveNow } from "../../../../../../common/utils/reactive-now/reactive-now";
|
||||
|
||||
const timeSinceUpdateWasDownloadedInjectable = getInjectable({
|
||||
id: "time-since-update-was-downloaded",
|
||||
|
||||
instantiate: (di) => {
|
||||
const updateDownloadedDateTime = di.inject(updateDownloadedDateTimeInjectable);
|
||||
|
||||
return computed(() => {
|
||||
const currentTimestamp = reactiveNow();
|
||||
|
||||
const downloadedAt = updateDownloadedDateTime.value.get();
|
||||
|
||||
assert(downloadedAt);
|
||||
|
||||
return currentTimestamp - (moment(downloadedAt).unix() * 1000);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default timeSinceUpdateWasDownloadedInjectable;
|
||||
+48
-30
@@ -12,43 +12,61 @@ exports[`periodical checking of updates given updater is enabled and configurati
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import periodicalCheckForUpdatesInjectable from "./periodical-check-for-updates.injectable";
|
||||
import { getGlobalOverride } from "../../../../../common/test-utils/get-global-override";
|
||||
|
||||
export default getGlobalOverride(periodicalCheckForUpdatesInjectable, () => ({
|
||||
start: async () => {},
|
||||
stop: async () => {},
|
||||
started: false,
|
||||
}));
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { getStartableStoppable } from "../../../../../common/utils/get-startable-stoppable";
|
||||
import processCheckingForUpdatesInjectable from "../../../main/process-checking-for-updates.injectable";
|
||||
import withOrphanPromiseInjectable from "../../../../../common/utils/with-orphan-promise/with-orphan-promise.injectable";
|
||||
|
||||
const periodicalCheckForUpdatesInjectable = getInjectable({
|
||||
id: "periodical-check-for-updates",
|
||||
|
||||
instantiate: (di) => {
|
||||
const withOrphanPromise = di.inject(withOrphanPromiseInjectable);
|
||||
const processCheckingForUpdates = withOrphanPromise(di.inject(processCheckingForUpdatesInjectable));
|
||||
|
||||
return getStartableStoppable("periodical-check-for-updates", () => {
|
||||
const TWO_HOURS = 1000 * 60 * 60 * 2;
|
||||
|
||||
processCheckingForUpdates("periodic");
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
|
||||
processCheckingForUpdates("periodic");
|
||||
}, TWO_HOURS);
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default periodicalCheckForUpdatesInjectable;
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import periodicalCheckForUpdatesInjectable from "./periodical-check-for-updates.injectable";
|
||||
import updatingIsEnabledInjectable from "../../../main/updating-is-enabled/updating-is-enabled.injectable";
|
||||
import { afterApplicationIsLoadedInjectionToken } from "../../../../../main/start-main-application/runnable-tokens/after-application-is-loaded-injection-token";
|
||||
|
||||
const startCheckingForUpdatesInjectable = getInjectable({
|
||||
id: "start-checking-for-updates",
|
||||
|
||||
instantiate: (di) => {
|
||||
const periodicalCheckForUpdates = di.inject(periodicalCheckForUpdatesInjectable);
|
||||
const updatingIsEnabled = di.inject(updatingIsEnabledInjectable);
|
||||
|
||||
return {
|
||||
id: "start-checking-for-updates",
|
||||
run: async () => {
|
||||
if (updatingIsEnabled && !periodicalCheckForUpdates.started) {
|
||||
await periodicalCheckForUpdates.start();
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: afterApplicationIsLoadedInjectionToken,
|
||||
});
|
||||
|
||||
export default startCheckingForUpdatesInjectable;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import periodicalCheckForUpdatesInjectable from "./periodical-check-for-updates.injectable";
|
||||
import { beforeQuitOfBackEndInjectionToken } from "../../../../../main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token";
|
||||
|
||||
const stopCheckingForUpdatesInjectable = getInjectable({
|
||||
id: "stop-checking-for-updates",
|
||||
|
||||
instantiate: (di) => {
|
||||
const periodicalCheckForUpdates = di.inject(periodicalCheckForUpdatesInjectable);
|
||||
|
||||
return {
|
||||
id: "stop-checking-for-updates",
|
||||
run: async () => {
|
||||
if (periodicalCheckForUpdates.started) {
|
||||
await periodicalCheckForUpdates.stop();
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: beforeQuitOfBackEndInjectionToken,
|
||||
});
|
||||
|
||||
export default stopCheckingForUpdatesInjectable;
|
||||
+7
-7
@@ -2,14 +2,14 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/process-checking-for-updates.injectable";
|
||||
import periodicalCheckForUpdatesInjectable from "./main/periodical-check-for-updates.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../../../common/test-utils/use-fake-time";
|
||||
|
||||
const ENOUGH_TIME = 1000 * 60 * 60 * 2;
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { preferenceItemInjectionToken } from "../../../../../preferences/renderer/preference-items/preference-item-injection-token";
|
||||
import { UpdateChannel } from "./update-channel";
|
||||
|
||||
const updateChannelPreferenceBlockInjectable = getInjectable({
|
||||
id: "update-channel-preference-item",
|
||||
|
||||
instantiate: () => ({
|
||||
kind: "block" as const,
|
||||
id: "update-channel",
|
||||
parentId: "application-page",
|
||||
orderNumber: 50,
|
||||
Component: UpdateChannel,
|
||||
}),
|
||||
|
||||
injectionToken: preferenceItemInjectionToken,
|
||||
});
|
||||
|
||||
export default updateChannelPreferenceBlockInjectable;
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import React from "react";
|
||||
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import { Select } from "../../../../../../renderer/components/select";
|
||||
import { updateChannels } from "../../../../common/update-channels";
|
||||
import type { SelectedUpdateChannel } from "../../../../common/selected-update-channel/selected-update-channel.injectable";
|
||||
import selectedUpdateChannelInjectable from "../../../../common/selected-update-channel/selected-update-channel.injectable";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { map, toPairs } from "lodash/fp";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
interface Dependencies {
|
||||
selectedUpdateChannel: SelectedUpdateChannel;
|
||||
}
|
||||
|
||||
const updateChannelOptions = pipeline(
|
||||
toPairs(updateChannels),
|
||||
|
||||
map(([, channel]) => ({
|
||||
value: channel.id,
|
||||
label: channel.label,
|
||||
})),
|
||||
);
|
||||
|
||||
|
||||
const NonInjectedUpdateChannel = observer(({ selectedUpdateChannel }: Dependencies) => (
|
||||
<section id="update-channel">
|
||||
<SubTitle title="Update Channel" />
|
||||
<Select
|
||||
id="update-channel-input"
|
||||
options={updateChannelOptions}
|
||||
value={selectedUpdateChannel.value.get().id}
|
||||
onChange={(selected) => selectedUpdateChannel.setValue(selected?.value)}
|
||||
themeName="lens"
|
||||
/>
|
||||
</section>
|
||||
));
|
||||
|
||||
export const UpdateChannel = withInjectables<Dependencies>(
|
||||
NonInjectedUpdateChannel,
|
||||
|
||||
{
|
||||
getProps: (di) => ({
|
||||
selectedUpdateChannel: di.inject(selectedUpdateChannelInjectable),
|
||||
}),
|
||||
},
|
||||
);
|
||||
+48
-30
@@ -12,43 +12,61 @@ exports[`selection of update stability when started renders 1`] = `
|
||||
<div
|
||||
class="items"
|
||||
>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="home-button"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="home"
|
||||
>
|
||||
home
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_back"
|
||||
>
|
||||
arrow_back
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="size-sm"
|
||||
/>
|
||||
<div
|
||||
class="preventedDragging"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
<i
|
||||
class="Icon material interactive disabled focusable"
|
||||
data-testid="history-forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="arrow_forward"
|
||||
>
|
||||
arrow_forward
|
||||
</span>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="items"
|
||||
/>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
+17
-16
@@ -2,27 +2,28 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import quitAndInstallUpdateInjectable from "../../main/quit-and-install-update.injectable";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import type { CheckForPlatformUpdates } from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable";
|
||||
import type { CheckForPlatformUpdates } from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { UpdateChannel, ReleaseChannel } from "../../common/application-update/update-channels";
|
||||
import { updateChannels } from "../../common/application-update/update-channels";
|
||||
import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import selectedUpdateChannelInjectable from "../../common/application-update/selected-update-channel/selected-update-channel.injectable";
|
||||
import type { UpdateChannel, ReleaseChannel } from "../../common/update-channels";
|
||||
import { updateChannels } from "../../common/update-channels";
|
||||
import type { DownloadPlatformUpdate } from "../../main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import selectedUpdateChannelInjectable from "../../common/selected-update-channel/selected-update-channel.injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
|
||||
import showInfoNotificationInjectable from "../../renderer/components/notifications/show-info-notification.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import setUpdateOnQuitInjectable from "../../../../main/electron-app/features/set-update-on-quit.injectable";
|
||||
import showInfoNotificationInjectable from "../../../../renderer/components/notifications/show-info-notification.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/process-checking-for-updates.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import getBuildVersionInjectable from "../../main/vars/build-version/get-build-version.injectable";
|
||||
import getBuildVersionInjectable
|
||||
from "../../../../main/vars/build-version/get-build-version.injectable";
|
||||
|
||||
describe("selection of update stability", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import createSyncBoxInjectable from "../../../../common/utils/sync-box/create-sync-box.injectable";
|
||||
import type { UpdateChannel } from "../update-channels";
|
||||
import type { SyncBox } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
import { syncBoxInjectionToken } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
|
||||
export type DiscoveredUpdateVersion = SyncBox<{ version: string; updateChannel: UpdateChannel } | null>;
|
||||
|
||||
const discoveredUpdateVersionInjectable = getInjectable({
|
||||
id: "discovered-update-version",
|
||||
|
||||
instantiate: (di) => {
|
||||
const createSyncBox = di.inject(createSyncBoxInjectable);
|
||||
|
||||
return createSyncBox(
|
||||
"discovered-update-version",
|
||||
null,
|
||||
) as DiscoveredUpdateVersion;
|
||||
},
|
||||
|
||||
injectionToken: syncBoxInjectionToken,
|
||||
});
|
||||
|
||||
export default discoveredUpdateVersionInjectable;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import createSyncBoxInjectable from "../../../../common/utils/sync-box/create-sync-box.injectable";
|
||||
import type { SyncBox } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
import { syncBoxInjectionToken } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
|
||||
export interface ProgressOfDownload {
|
||||
percentage: number;
|
||||
failed?: string;
|
||||
}
|
||||
|
||||
export type ProgressOfUpdateDownload = SyncBox<ProgressOfDownload>;
|
||||
|
||||
const progressOfUpdateDownloadInjectable = getInjectable({
|
||||
id: "progress-of-update-download-state",
|
||||
|
||||
instantiate: (di) => {
|
||||
const createSyncBox = di.inject(createSyncBoxInjectable);
|
||||
|
||||
return createSyncBox<ProgressOfDownload>("progress-of-update-download", { percentage: 0 });
|
||||
},
|
||||
|
||||
injectionToken: syncBoxInjectionToken,
|
||||
});
|
||||
|
||||
export default progressOfUpdateDownloadInjectable;
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { MessageChannel } from "../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
export type RestartAndInstallUpdateChannel = MessageChannel<void>;
|
||||
|
||||
export const restartAndInstallUpdateChannel: RestartAndInstallUpdateChannel = {
|
||||
id: "restart-and-install-update-channel",
|
||||
};
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import releaseChannelInjectable from "../../../../common/vars/release-channel.injectable";
|
||||
import { updateChannels } from "../update-channels";
|
||||
import { createInitializableState } from "../../../../common/initializable-state/create";
|
||||
|
||||
const defaultUpdateChannelInjectable = createInitializableState({
|
||||
id: "default-update-channel",
|
||||
init: (di) => updateChannels[di.inject(releaseChannelInjectable).get()],
|
||||
});
|
||||
|
||||
export default defaultUpdateChannelInjectable;
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { action, computed, observable } from "mobx";
|
||||
import type { UpdateChannel, ReleaseChannel } from "../update-channels";
|
||||
import { updateChannels } from "../update-channels";
|
||||
import defaultUpdateChannelInjectable from "./default-update-channel.injectable";
|
||||
|
||||
export interface SelectedUpdateChannel {
|
||||
value: IComputedValue<UpdateChannel>;
|
||||
setValue: (channelId?: ReleaseChannel) => void;
|
||||
}
|
||||
|
||||
const selectedUpdateChannelInjectable = getInjectable({
|
||||
id: "selected-update-channel",
|
||||
|
||||
instantiate: (di): SelectedUpdateChannel => {
|
||||
const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable);
|
||||
const state = observable.box<UpdateChannel>(undefined, { deep: false });
|
||||
|
||||
return {
|
||||
value: computed(() => state.get() ?? defaultUpdateChannel.get()),
|
||||
|
||||
setValue: action((channelId) => {
|
||||
const targetUpdateChannel =
|
||||
channelId && updateChannels[channelId]
|
||||
? updateChannels[channelId]
|
||||
: defaultUpdateChannel.get();
|
||||
|
||||
state.set(targetUpdateChannel);
|
||||
}),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default selectedUpdateChannelInjectable;
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
|
||||
export type ReleaseChannel = "alpha" | "beta" | "latest";
|
||||
|
||||
const latestChannel: UpdateChannel = {
|
||||
id: "latest",
|
||||
label: "Stable",
|
||||
moreStableUpdateChannel: null,
|
||||
};
|
||||
|
||||
const betaChannel: UpdateChannel = {
|
||||
id: "beta",
|
||||
label: "Beta",
|
||||
moreStableUpdateChannel: latestChannel,
|
||||
};
|
||||
|
||||
const alphaChannel: UpdateChannel = {
|
||||
id: "alpha",
|
||||
label: "Alpha",
|
||||
moreStableUpdateChannel: betaChannel,
|
||||
};
|
||||
|
||||
export const updateChannels = {
|
||||
latest: latestChannel,
|
||||
beta: betaChannel,
|
||||
alpha: alphaChannel,
|
||||
};
|
||||
|
||||
export interface UpdateChannel {
|
||||
readonly id: ReleaseChannel;
|
||||
readonly label: string;
|
||||
readonly moreStableUpdateChannel: UpdateChannel | null;
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import createSyncBoxInjectable from "../../../../common/utils/sync-box/create-sync-box.injectable";
|
||||
import { syncBoxInjectionToken } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
|
||||
const updateDownloadedDateTimeInjectable = getInjectable({
|
||||
id: "update-downloaded-date-time",
|
||||
|
||||
instantiate: (di) => {
|
||||
const createSyncBox = di.inject(createSyncBoxInjectable);
|
||||
|
||||
return createSyncBox<string | null>(
|
||||
"update-downloaded-date-time",
|
||||
null,
|
||||
);
|
||||
},
|
||||
|
||||
injectionToken: syncBoxInjectionToken,
|
||||
});
|
||||
|
||||
export default updateDownloadedDateTimeInjectable;
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import createSyncBoxInjectable from "../../../../common/utils/sync-box/create-sync-box.injectable";
|
||||
import type { SyncBox } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
import { syncBoxInjectionToken } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
|
||||
export type UpdateIsBeingDownloaded = SyncBox<boolean>;
|
||||
|
||||
const updateIsBeingDownloadedInjectable = getInjectable({
|
||||
id: "update-is-being-downloaded",
|
||||
|
||||
instantiate: (di) => {
|
||||
const createSyncBox = di.inject(createSyncBoxInjectable);
|
||||
|
||||
return createSyncBox("update-is-being-downloaded", false);
|
||||
},
|
||||
|
||||
injectionToken: syncBoxInjectionToken,
|
||||
});
|
||||
|
||||
export default updateIsBeingDownloadedInjectable;
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import createSyncBoxInjectable from "../../../../common/utils/sync-box/create-sync-box.injectable";
|
||||
import type { SyncBox } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
import { syncBoxInjectionToken } from "../../../../common/utils/sync-box/sync-box-injection-token";
|
||||
|
||||
export type UpdatesAreBeingDiscovered = SyncBox<boolean>;
|
||||
|
||||
const updatesAreBeingDiscoveredInjectable = getInjectable({
|
||||
id: "updates-are-being-discovered",
|
||||
|
||||
instantiate: (di) => {
|
||||
const createSyncBox = di.inject(createSyncBoxInjectable);
|
||||
|
||||
return createSyncBox("updates-are-being-discovered", false);
|
||||
},
|
||||
|
||||
injectionToken: syncBoxInjectionToken,
|
||||
});
|
||||
|
||||
export default updatesAreBeingDiscoveredInjectable;
|
||||
@@ -5,15 +5,15 @@
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import publishIsConfiguredInjectable from "./main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { CheckForPlatformUpdates } from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import selectedUpdateChannelInjectable from "../../common/application-update/selected-update-channel/selected-update-channel.injectable";
|
||||
import type { CheckForPlatformUpdates } from "./main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "./main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import processCheckingForUpdatesInjectable from "./main/process-checking-for-updates.injectable";
|
||||
import selectedUpdateChannelInjectable from "./common/selected-update-channel/selected-update-channel.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { updateChannels } from "../../common/application-update/update-channels";
|
||||
import { updateChannels } from "./common/update-channels";
|
||||
import getBuildVersionInjectable from "../../main/vars/build-version/get-build-version.injectable";
|
||||
|
||||
describe("downgrading version update", () => {
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
*/
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||
import quitAndInstallUpdateInjectable from "./main/quit-and-install-update.injectable";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import type { CheckForPlatformUpdates } from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import publishIsConfiguredInjectable from "./main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable";
|
||||
import type { CheckForPlatformUpdates } from "./main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "./main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import type { DownloadPlatformUpdate } from "./main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "./main/download-update/download-platform-update/download-platform-update.injectable";
|
||||
import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import processCheckingForUpdatesInjectable from "./main/process-checking-for-updates.injectable";
|
||||
import { useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable";
|
||||
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import checkForPlatformUpdatesInjectable from "./check-for-platform-updates.injectable";
|
||||
import { getGlobalOverrideForFunction } from "../../../../../common/test-utils/get-global-override-for-function";
|
||||
|
||||
export default getGlobalOverrideForFunction(checkForPlatformUpdatesInjectable);
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronUpdaterInjectable from "../../../../../main/electron-app/features/electron-updater.injectable";
|
||||
import type { UpdateChannel } from "../../../common/update-channels";
|
||||
import loggerInjectable from "../../../../../common/logger.injectable";
|
||||
import type { UpdateCheckResult } from "electron-updater";
|
||||
|
||||
export type CheckForUpdatesResult = {
|
||||
updateWasDiscovered: false;
|
||||
} | {
|
||||
updateWasDiscovered: true;
|
||||
version: string;
|
||||
};
|
||||
|
||||
export type CheckForPlatformUpdates = (updateChannel: UpdateChannel, opts: { allowDowngrade: boolean }) => Promise<CheckForUpdatesResult>;
|
||||
|
||||
const checkForPlatformUpdatesInjectable = getInjectable({
|
||||
id: "check-for-platform-updates",
|
||||
|
||||
instantiate: (di): CheckForPlatformUpdates => {
|
||||
const electronUpdater = di.inject(electronUpdaterInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (updateChannel, { allowDowngrade }) => {
|
||||
electronUpdater.channel = updateChannel.id;
|
||||
electronUpdater.autoDownload = false;
|
||||
electronUpdater.allowDowngrade = allowDowngrade;
|
||||
|
||||
let result: UpdateCheckResult;
|
||||
|
||||
try {
|
||||
result = await electronUpdater.checkForUpdates();
|
||||
} catch (error) {
|
||||
logger.error("[UPDATE-APP/CHECK-FOR-UPDATES]", error);
|
||||
|
||||
return {
|
||||
updateWasDiscovered: false,
|
||||
};
|
||||
}
|
||||
|
||||
const { updateInfo, cancellationToken } = result;
|
||||
|
||||
if (!cancellationToken) {
|
||||
return {
|
||||
updateWasDiscovered: false,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
updateWasDiscovered: true,
|
||||
version: updateInfo.version,
|
||||
};
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default checkForPlatformUpdatesInjectable;
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getDiForUnitTesting } from "../../../../../main/getDiForUnitTesting";
|
||||
import electronUpdaterInjectable from "../../../../../main/electron-app/features/electron-updater.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { AppUpdater, UpdateCheckResult } from "electron-updater";
|
||||
import type { CheckForPlatformUpdates } from "./check-for-platform-updates.injectable";
|
||||
import checkForPlatformUpdatesInjectable from "./check-for-platform-updates.injectable";
|
||||
import type { UpdateChannel, ReleaseChannel } from "../../../common/update-channels";
|
||||
import { getPromiseStatus } from "../../../../../common/test-utils/get-promise-status";
|
||||
import loggerInjectable from "../../../../../common/logger.injectable";
|
||||
import type { Logger } from "../../../../../common/logger";
|
||||
|
||||
describe("check-for-platform-updates", () => {
|
||||
let checkForPlatformUpdates: CheckForPlatformUpdates;
|
||||
let electronUpdaterFake: AppUpdater;
|
||||
let checkForUpdatesMock: AsyncFnMock<() => UpdateCheckResult>;
|
||||
let logErrorMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
const di = getDiForUnitTesting();
|
||||
|
||||
checkForUpdatesMock = asyncFn();
|
||||
|
||||
electronUpdaterFake = {
|
||||
channel: undefined,
|
||||
autoDownload: undefined,
|
||||
allowDowngrade: undefined,
|
||||
|
||||
checkForUpdates: checkForUpdatesMock,
|
||||
} as unknown as AppUpdater;
|
||||
|
||||
di.override(electronUpdaterInjectable, () => electronUpdaterFake);
|
||||
|
||||
logErrorMock = jest.fn();
|
||||
|
||||
di.override(loggerInjectable, () => ({ error: logErrorMock }) as unknown as Logger);
|
||||
|
||||
checkForPlatformUpdates = di.inject(checkForPlatformUpdatesInjectable);
|
||||
});
|
||||
|
||||
describe("when called", () => {
|
||||
let actualPromise: Promise<any>;
|
||||
|
||||
beforeEach(() => {
|
||||
const testUpdateChannel: UpdateChannel = {
|
||||
id: "some-update-channel" as ReleaseChannel,
|
||||
label: "Some update channel",
|
||||
moreStableUpdateChannel: null,
|
||||
};
|
||||
|
||||
actualPromise = checkForPlatformUpdates(testUpdateChannel, { allowDowngrade: true });
|
||||
});
|
||||
|
||||
it("sets update channel", () => {
|
||||
expect(electronUpdaterFake.channel).toBe("some-update-channel");
|
||||
});
|
||||
|
||||
it("sets flag for allowing downgrade", () => {
|
||||
expect(electronUpdaterFake.allowDowngrade).toBe(true);
|
||||
});
|
||||
|
||||
it("disables auto downloading for being controlled", () => {
|
||||
expect(electronUpdaterFake.autoDownload).toBe(false);
|
||||
});
|
||||
|
||||
it("checks for updates", () => {
|
||||
expect(checkForUpdatesMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not resolve yet", async () => {
|
||||
const promiseStatus = await getPromiseStatus(actualPromise);
|
||||
|
||||
expect(promiseStatus.fulfilled).toBe(false);
|
||||
});
|
||||
|
||||
it("when checking for updates resolves with update, resolves with the discovered update", async () => {
|
||||
await checkForUpdatesMock.resolve({
|
||||
updateInfo: {
|
||||
version: "some-version",
|
||||
},
|
||||
|
||||
cancellationToken: "some-cancellation-token",
|
||||
} as unknown as UpdateCheckResult);
|
||||
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toEqual({ updateWasDiscovered: true, version: "some-version" });
|
||||
});
|
||||
|
||||
it("when checking for updates resolves without update, resolves with update not being discovered", async () => {
|
||||
await checkForUpdatesMock.resolve({
|
||||
updateInfo: {
|
||||
version: "some-version-that-matches-to-current-installed-version",
|
||||
},
|
||||
|
||||
cancellationToken: null,
|
||||
} as unknown as UpdateCheckResult);
|
||||
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toEqual({ updateWasDiscovered: false });
|
||||
});
|
||||
|
||||
describe("when checking for updates rejects", () => {
|
||||
let errorStub: Error;
|
||||
|
||||
beforeEach(() => {
|
||||
errorStub = new Error("Some error");
|
||||
|
||||
checkForUpdatesMock.reject(errorStub);
|
||||
});
|
||||
|
||||
it("logs errors", () => {
|
||||
expect(logErrorMock).toHaveBeenCalledWith("[UPDATE-APP/CHECK-FOR-UPDATES]", errorStub);
|
||||
});
|
||||
|
||||
it("resolves with update not being discovered", async () => {
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toEqual({ updateWasDiscovered: false });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { UpdateChannel } from "../../common/update-channels";
|
||||
import checkForPlatformUpdatesInjectable from "./check-for-platform-updates/check-for-platform-updates.injectable";
|
||||
import updateCanBeDowngradedInjectable from "./update-can-be-downgraded.injectable";
|
||||
|
||||
export type CheckForUpdatesFromChannelResult = {
|
||||
updateWasDiscovered: false;
|
||||
} | {
|
||||
updateWasDiscovered: true;
|
||||
version: string;
|
||||
actualUpdateChannel: UpdateChannel;
|
||||
};
|
||||
|
||||
const checkForUpdatesStartingFromChannelInjectable = getInjectable({
|
||||
id: "check-for-updates-starting-from-channel",
|
||||
|
||||
instantiate: (di) => {
|
||||
const checkForPlatformUpdates = di.inject(checkForPlatformUpdatesInjectable);
|
||||
const updateCanBeDowngraded = di.inject(updateCanBeDowngradedInjectable);
|
||||
|
||||
const _recursiveCheck = async (
|
||||
updateChannel: UpdateChannel,
|
||||
): Promise<CheckForUpdatesFromChannelResult> => {
|
||||
const result = await checkForPlatformUpdates(updateChannel, {
|
||||
allowDowngrade: updateCanBeDowngraded.get(),
|
||||
});
|
||||
|
||||
if (result.updateWasDiscovered) {
|
||||
return {
|
||||
updateWasDiscovered: true,
|
||||
version: result.version,
|
||||
actualUpdateChannel: updateChannel,
|
||||
};
|
||||
}
|
||||
|
||||
if (updateChannel.moreStableUpdateChannel) {
|
||||
return await _recursiveCheck(updateChannel.moreStableUpdateChannel);
|
||||
}
|
||||
|
||||
return { updateWasDiscovered: false };
|
||||
};
|
||||
|
||||
return _recursiveCheck;
|
||||
},
|
||||
});
|
||||
|
||||
export default checkForUpdatesStartingFromChannelInjectable;
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import selectedUpdateChannelInjectable from "../../common/selected-update-channel/selected-update-channel.injectable";
|
||||
import releaseChannelInjectable from "../../../../common/vars/release-channel.injectable";
|
||||
|
||||
const updateCanBeDowngradedInjectable = getInjectable({
|
||||
id: "update-can-be-downgraded",
|
||||
|
||||
instantiate: (di) => {
|
||||
const selectedUpdateChannel = di.inject(selectedUpdateChannelInjectable);
|
||||
const releaseChannel = di.inject(releaseChannelInjectable);
|
||||
|
||||
return computed(() => (
|
||||
selectedUpdateChannel.value.get().id === "latest"
|
||||
&& releaseChannel.get() !== "latest"
|
||||
));
|
||||
},
|
||||
});
|
||||
|
||||
export default updateCanBeDowngradedInjectable;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getGlobalOverrideForFunction } from "../../../../../common/test-utils/get-global-override-for-function";
|
||||
import downloadPlatformUpdateInjectable from "./download-platform-update.injectable";
|
||||
|
||||
export default getGlobalOverrideForFunction(downloadPlatformUpdateInjectable);
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronUpdaterInjectable from "../../../../../main/electron-app/features/electron-updater.injectable";
|
||||
import loggerInjectable from "../../../../../common/logger.injectable";
|
||||
import type { ProgressInfo } from "electron-updater";
|
||||
import type { ProgressOfDownload } from "../../../common/progress-of-update-download/progress-of-update-download.injectable";
|
||||
|
||||
export type DownloadPlatformUpdate = (
|
||||
onDownloadProgress: (arg: ProgressOfDownload) => void
|
||||
) => Promise<{ downloadWasSuccessful: boolean }>;
|
||||
|
||||
const downloadPlatformUpdateInjectable = getInjectable({
|
||||
id: "download-platform-update",
|
||||
|
||||
instantiate: (di): DownloadPlatformUpdate => {
|
||||
const electronUpdater = di.inject(electronUpdaterInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async (onDownloadProgress) => {
|
||||
onDownloadProgress({ percentage: 0 });
|
||||
|
||||
const updateDownloadProgress = ({ percent: percentage }: ProgressInfo) =>
|
||||
onDownloadProgress({ percentage });
|
||||
|
||||
electronUpdater.on("download-progress", updateDownloadProgress);
|
||||
|
||||
try {
|
||||
await electronUpdater.downloadUpdate();
|
||||
} catch(error) {
|
||||
logger.error("[UPDATE-APP/DOWNLOAD]", error);
|
||||
|
||||
return { downloadWasSuccessful: false };
|
||||
} finally {
|
||||
electronUpdater.off("download-progress", updateDownloadProgress);
|
||||
}
|
||||
|
||||
return { downloadWasSuccessful: true };
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default downloadPlatformUpdateInjectable;
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getDiForUnitTesting } from "../../../../../main/getDiForUnitTesting";
|
||||
import electronUpdaterInjectable from "../../../../../main/electron-app/features/electron-updater.injectable";
|
||||
import type { DownloadPlatformUpdate } from "./download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "./download-platform-update.injectable";
|
||||
import type { AppUpdater } from "electron-updater";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import { getPromiseStatus } from "../../../../../common/test-utils/get-promise-status";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import loggerInjectable from "../../../../../common/logger.injectable";
|
||||
import type { Logger } from "../../../../../common/logger";
|
||||
|
||||
describe("download-platform-update", () => {
|
||||
let downloadPlatformUpdate: DownloadPlatformUpdate;
|
||||
let downloadUpdateMock: AsyncFnMock<() => void>;
|
||||
let electronUpdaterFake: AppUpdater;
|
||||
let electronUpdaterOnMock: jest.Mock;
|
||||
let electronUpdaterOffMock: jest.Mock;
|
||||
let di: DiContainer;
|
||||
let logErrorMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
di = getDiForUnitTesting();
|
||||
|
||||
downloadUpdateMock = asyncFn();
|
||||
electronUpdaterOnMock = jest.fn();
|
||||
electronUpdaterOffMock = jest.fn();
|
||||
|
||||
electronUpdaterFake = {
|
||||
channel: undefined,
|
||||
autoDownload: undefined,
|
||||
|
||||
on: electronUpdaterOnMock,
|
||||
off: electronUpdaterOffMock,
|
||||
|
||||
downloadUpdate: downloadUpdateMock,
|
||||
} as unknown as AppUpdater;
|
||||
|
||||
di.override(electronUpdaterInjectable, () => electronUpdaterFake);
|
||||
|
||||
logErrorMock = jest.fn();
|
||||
di.override(loggerInjectable, () => ({ error: logErrorMock }) as unknown as Logger);
|
||||
|
||||
downloadPlatformUpdate = di.inject(downloadPlatformUpdateInjectable);
|
||||
});
|
||||
|
||||
describe("when called", () => {
|
||||
let actualPromise: Promise<{ downloadWasSuccessful: boolean }>;
|
||||
let onDownloadProgressMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
onDownloadProgressMock = jest.fn();
|
||||
|
||||
actualPromise = downloadPlatformUpdate(onDownloadProgressMock);
|
||||
});
|
||||
|
||||
it("calls for downloading of update", () => {
|
||||
expect(downloadUpdateMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not resolve yet", async () => {
|
||||
const promiseStatus = await getPromiseStatus(actualPromise);
|
||||
|
||||
expect(promiseStatus.fulfilled).toBe(false);
|
||||
});
|
||||
|
||||
it("starts progress of download from 0", () => {
|
||||
expect(onDownloadProgressMock).toHaveBeenCalledWith({ percentage: 0 });
|
||||
});
|
||||
|
||||
describe("when downloading progresses", () => {
|
||||
beforeEach(() => {
|
||||
onDownloadProgressMock.mockClear();
|
||||
|
||||
const [, callback] = electronUpdaterOnMock.mock.calls.find(
|
||||
([event]) => event === "download-progress",
|
||||
);
|
||||
|
||||
callback({
|
||||
percent: 42,
|
||||
total: 0,
|
||||
delta: 0,
|
||||
transferred: 0,
|
||||
bytesPerSecond: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("updates progress of the download", () => {
|
||||
expect(onDownloadProgressMock).toHaveBeenCalledWith({ percentage: 42 });
|
||||
});
|
||||
|
||||
describe("when downloading resolves", () => {
|
||||
beforeEach(async () => {
|
||||
onDownloadProgressMock.mockClear();
|
||||
|
||||
await downloadUpdateMock.resolve();
|
||||
});
|
||||
|
||||
it("resolves with success", async () => {
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toEqual({ downloadWasSuccessful: true });
|
||||
});
|
||||
|
||||
it("does not reset progress of download yet", () => {
|
||||
expect(onDownloadProgressMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("stops watching for download progress", () => {
|
||||
expect(electronUpdaterOffMock).toHaveBeenCalledWith(
|
||||
"download-progress",
|
||||
expect.any(Function),
|
||||
);
|
||||
});
|
||||
|
||||
it("when starting download again, resets progress of download", () => {
|
||||
downloadPlatformUpdate(onDownloadProgressMock);
|
||||
|
||||
expect(onDownloadProgressMock).toHaveBeenCalledWith({ percentage: 0 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("when downloading rejects", () => {
|
||||
let errorStub: Error;
|
||||
|
||||
beforeEach(() => {
|
||||
errorStub = new Error("Some error");
|
||||
|
||||
downloadUpdateMock.reject(errorStub);
|
||||
});
|
||||
|
||||
it("logs error", () => {
|
||||
expect(logErrorMock).toHaveBeenCalledWith("[UPDATE-APP/DOWNLOAD]", errorStub);
|
||||
});
|
||||
|
||||
it("stops watching for download progress", () => {
|
||||
expect(electronUpdaterOffMock).toHaveBeenCalledWith(
|
||||
"download-progress",
|
||||
expect.any(Function),
|
||||
);
|
||||
});
|
||||
|
||||
it("resolves with failure", async () => {
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toEqual({ downloadWasSuccessful: false });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import downloadPlatformUpdateInjectable from "./download-platform-update/download-platform-update.injectable";
|
||||
import updateIsBeingDownloadedInjectable from "../../common/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||
import discoveredUpdateVersionInjectable from "../../common/discovered-update-version/discovered-update-version.injectable";
|
||||
import { action, runInAction } from "mobx";
|
||||
import type { ProgressOfDownload } from "../../common/progress-of-update-download/progress-of-update-download.injectable";
|
||||
import progressOfUpdateDownloadInjectable from "../../common/progress-of-update-download/progress-of-update-download.injectable";
|
||||
import { getCurrentDateTime } from "../../../../common/utils/date/get-current-date-time";
|
||||
import updateDownloadedDateTimeInjectable from "../../common/update-downloaded-date-time/update-downloaded-date-time.injectable";
|
||||
|
||||
const downloadUpdateInjectable = getInjectable({
|
||||
id: "download-update",
|
||||
|
||||
instantiate: (di) => {
|
||||
const downloadPlatformUpdate = di.inject(downloadPlatformUpdateInjectable);
|
||||
const downloadingUpdateState = di.inject(updateIsBeingDownloadedInjectable);
|
||||
const discoveredVersionState = di.inject(discoveredUpdateVersionInjectable);
|
||||
const progressOfUpdateDownload = di.inject(progressOfUpdateDownloadInjectable);
|
||||
const updateDownloadedDate = di.inject(updateDownloadedDateTimeInjectable);
|
||||
|
||||
const updateDownloadProgress = action((progressOfDownload: ProgressOfDownload) => {
|
||||
progressOfUpdateDownload.set(progressOfDownload);
|
||||
});
|
||||
|
||||
return async () => {
|
||||
runInAction(() => {
|
||||
progressOfUpdateDownload.set({ percentage: 0 });
|
||||
downloadingUpdateState.set(true);
|
||||
});
|
||||
|
||||
const { downloadWasSuccessful } = await downloadPlatformUpdate(
|
||||
updateDownloadProgress,
|
||||
);
|
||||
|
||||
runInAction(() => {
|
||||
if (!downloadWasSuccessful) {
|
||||
progressOfUpdateDownload.set({ percentage: 0, failed: "Download of update failed" });
|
||||
discoveredVersionState.set(null);
|
||||
}
|
||||
|
||||
const currentDateTime = getCurrentDateTime();
|
||||
|
||||
updateDownloadedDate.set(currentDateTime);
|
||||
|
||||
downloadingUpdateState.set(false);
|
||||
});
|
||||
|
||||
return { downloadWasSuccessful };
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default downloadUpdateInjectable;
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { afterApplicationIsLoadedInjectionToken } from "../../../main/start-main-application/runnable-tokens/after-application-is-loaded-injection-token";
|
||||
import emitEventInjectable from "../../../common/app-event-bus/emit-event.injectable";
|
||||
import { getCurrentDateTime } from "../../../common/utils/date/get-current-date-time";
|
||||
import buildVersionInjectable from "../../../main/vars/build-version/build-version.injectable";
|
||||
|
||||
const emitCurrentVersionToAnalyticsInjectable = getInjectable({
|
||||
id: "emit-current-version-to-analytics",
|
||||
|
||||
instantiate: (di) => {
|
||||
const emitEvent = di.inject(emitEventInjectable);
|
||||
const buildVersion = di.inject(buildVersionInjectable);
|
||||
|
||||
return {
|
||||
id: "emit-current-version-to-analytics",
|
||||
run: () => {
|
||||
emitEvent({
|
||||
name: "app",
|
||||
action: "current-version",
|
||||
|
||||
params: {
|
||||
version: buildVersion.get(),
|
||||
currentDateTime: getCurrentDateTime(),
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: afterApplicationIsLoadedInjectionToken,
|
||||
});
|
||||
|
||||
export default emitCurrentVersionToAnalyticsInjectable;
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import selectedUpdateChannelInjectable from "../common/selected-update-channel/selected-update-channel.injectable";
|
||||
import updatesAreBeingDiscoveredInjectable from "../common/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||
import discoveredUpdateVersionInjectable from "../common/discovered-update-version/discovered-update-version.injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import downloadUpdateInjectable from "./download-update/download-update.injectable";
|
||||
import checkForUpdatesStartingFromChannelInjectable from "./check-for-updates/check-for-updates-starting-from-channel.injectable";
|
||||
import emitEventInjectable from "../../../common/app-event-bus/emit-event.injectable";
|
||||
import { getCurrentDateTime } from "../../../common/utils/date/get-current-date-time";
|
||||
|
||||
const processCheckingForUpdatesInjectable = getInjectable({
|
||||
id: "process-checking-for-updates",
|
||||
|
||||
instantiate: (di) => {
|
||||
const downloadUpdate = di.inject(downloadUpdateInjectable);
|
||||
const selectedUpdateChannel = di.inject(selectedUpdateChannelInjectable);
|
||||
const checkingForUpdatesState = di.inject(updatesAreBeingDiscoveredInjectable);
|
||||
const discoveredVersionState = di.inject(discoveredUpdateVersionInjectable);
|
||||
const checkForUpdatesStartingFromChannel = di.inject(checkForUpdatesStartingFromChannelInjectable);
|
||||
const emitEvent = di.inject(emitEventInjectable);
|
||||
|
||||
return async (source: string) => {
|
||||
emitEvent({
|
||||
name: "app",
|
||||
action: "checking-for-updates",
|
||||
params: { currentDateTime: getCurrentDateTime(), source },
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
checkingForUpdatesState.set(true);
|
||||
});
|
||||
|
||||
const result = await checkForUpdatesStartingFromChannel(selectedUpdateChannel.value.get());
|
||||
|
||||
if (!result.updateWasDiscovered) {
|
||||
runInAction(() => {
|
||||
discoveredVersionState.set(null);
|
||||
checkingForUpdatesState.set(false);
|
||||
});
|
||||
|
||||
return { updateIsReadyToBeInstalled: false };
|
||||
}
|
||||
|
||||
const { version, actualUpdateChannel } = result;
|
||||
|
||||
const previouslyDiscovered = discoveredVersionState.value.get();
|
||||
|
||||
if (version === previouslyDiscovered?.version) {
|
||||
runInAction(() => {
|
||||
checkingForUpdatesState.set(false);
|
||||
});
|
||||
|
||||
return { updateIsReadyToBeInstalled: true };
|
||||
}
|
||||
|
||||
emitEvent({
|
||||
name: "app",
|
||||
action: "update-was-discovered",
|
||||
params: { version, currentDateTime: getCurrentDateTime() },
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
discoveredVersionState.set({
|
||||
version,
|
||||
updateChannel: actualUpdateChannel,
|
||||
});
|
||||
|
||||
checkingForUpdatesState.set(false);
|
||||
});
|
||||
|
||||
const { downloadWasSuccessful } = await downloadUpdate();
|
||||
|
||||
return { updateIsReadyToBeInstalled: downloadWasSuccessful };
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default processCheckingForUpdatesInjectable;
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronQuitAndInstallUpdateInjectable from "../../../main/electron-app/features/electron-quit-and-install-update.injectable";
|
||||
import { getCurrentDateTime } from "../../../common/utils/date/get-current-date-time";
|
||||
import emitEventInjectable from "../../../common/app-event-bus/emit-event.injectable";
|
||||
import discoveredUpdateVersionInjectable from "../common/discovered-update-version/discovered-update-version.injectable";
|
||||
|
||||
const quitAndInstallUpdateInjectable = getInjectable({
|
||||
id: "quit-and-install-update",
|
||||
|
||||
instantiate: (di) => {
|
||||
const electronQuitAndInstallUpdate = di.inject(
|
||||
electronQuitAndInstallUpdateInjectable,
|
||||
);
|
||||
|
||||
const emitEvent = di.inject(emitEventInjectable);
|
||||
const discoveredUpdateVersion = di.inject(discoveredUpdateVersionInjectable);
|
||||
|
||||
return () => {
|
||||
const discoveredVersion = discoveredUpdateVersion.value.get();
|
||||
|
||||
if (!discoveredVersion) {
|
||||
throw new Error("Tried to install update but no update was discovered.");
|
||||
}
|
||||
|
||||
emitEvent({
|
||||
name: "app",
|
||||
action: "start-installing-update",
|
||||
|
||||
params: {
|
||||
version: discoveredVersion.version,
|
||||
updateChannel: discoveredVersion.updateChannel.id,
|
||||
currentDateTime: getCurrentDateTime(),
|
||||
},
|
||||
});
|
||||
|
||||
electronQuitAndInstallUpdate();
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default quitAndInstallUpdateInjectable;
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { restartAndInstallUpdateChannel } from "../../common/restart-and-install-update-channel";
|
||||
import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import quitAndInstallUpdateInjectable from "../quit-and-install-update.injectable";
|
||||
|
||||
const restartAndInstallUpdateListenerInjectable = getMessageChannelListenerInjectable({
|
||||
id: "restart",
|
||||
channel: restartAndInstallUpdateChannel,
|
||||
handler: (di) => di.inject(quitAndInstallUpdateInjectable),
|
||||
});
|
||||
|
||||
export default restartAndInstallUpdateListenerInjectable;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getGlobalOverride } from "../../../../../common/test-utils/get-global-override";
|
||||
import publishIsConfiguredInjectable from "./publish-is-configured.injectable";
|
||||
|
||||
export default getGlobalOverride(publishIsConfiguredInjectable, () => false);
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import applicationInformationInjectable from "../../../../../common/vars/application-information.injectable";
|
||||
|
||||
const publishIsConfiguredInjectable = getInjectable({
|
||||
id: "publish-is-configured",
|
||||
instantiate: (di) => Boolean(di.inject(applicationInformationInjectable).build.publish?.length),
|
||||
});
|
||||
|
||||
export default publishIsConfiguredInjectable;
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "./publish-is-configured/publish-is-configured.injectable";
|
||||
|
||||
const updatingIsEnabledInjectable = getInjectable({
|
||||
id: "updating-is-enabled",
|
||||
|
||||
instantiate: (di) => {
|
||||
const electronUpdaterIsActive = di.inject(electronUpdaterIsActiveInjectable);
|
||||
const publishIsConfigured = di.inject(publishIsConfiguredInjectable);
|
||||
|
||||
return electronUpdaterIsActive && publishIsConfigured;
|
||||
},
|
||||
});
|
||||
|
||||
export default updatingIsEnabledInjectable;
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { onLoadOfApplicationInjectionToken } from "../../../../main/start-main-application/runnable-tokens/on-load-of-application-injection-token";
|
||||
import watchIfUpdateShouldHappenOnQuitInjectable from "./watch-if-update-should-happen-on-quit.injectable";
|
||||
|
||||
const startWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({
|
||||
id: "start-watching-if-update-should-happen-on-quit",
|
||||
|
||||
instantiate: (di) => {
|
||||
const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable);
|
||||
|
||||
return {
|
||||
id: "start-watching-if-update-should-happen-on-quit",
|
||||
run: () => {
|
||||
watchIfUpdateShouldHappenOnQuit.start();
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: onLoadOfApplicationInjectionToken,
|
||||
});
|
||||
|
||||
export default startWatchingIfUpdateShouldHappenOnQuitInjectable;
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import watchIfUpdateShouldHappenOnQuitInjectable from "./watch-if-update-should-happen-on-quit.injectable";
|
||||
import { beforeQuitOfBackEndInjectionToken } from "../../../../main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token";
|
||||
|
||||
const stopWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({
|
||||
id: "stop-watching-if-update-should-happen-on-quit",
|
||||
|
||||
instantiate: (di) => {
|
||||
const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable);
|
||||
|
||||
return {
|
||||
id: "stop-watching-if-update-should-happen-on-quit",
|
||||
run: () => {
|
||||
watchIfUpdateShouldHappenOnQuit.stop();
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: beforeQuitOfBackEndInjectionToken,
|
||||
});
|
||||
|
||||
export default stopWatchingIfUpdateShouldHappenOnQuitInjectable;
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { autorun } from "mobx";
|
||||
import { getStartableStoppable } from "../../../../common/utils/get-startable-stoppable";
|
||||
import setUpdateOnQuitInjectable from "../../../../main/electron-app/features/set-update-on-quit.injectable";
|
||||
import selectedUpdateChannelInjectable from "../../common/selected-update-channel/selected-update-channel.injectable";
|
||||
import type { ReleaseChannel, UpdateChannel } from "../../common/update-channels";
|
||||
import discoveredUpdateVersionInjectable from "../../common/discovered-update-version/discovered-update-version.injectable";
|
||||
|
||||
const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({
|
||||
id: "watch-if-update-should-happen-on-quit",
|
||||
|
||||
instantiate: (di) => {
|
||||
const setUpdateOnQuit = di.inject(setUpdateOnQuitInjectable);
|
||||
const selectedUpdateChannel = di.inject(selectedUpdateChannelInjectable);
|
||||
const discoveredVersionState = di.inject(discoveredUpdateVersionInjectable);
|
||||
|
||||
return getStartableStoppable("watch-if-update-should-happen-on-quit", () =>
|
||||
autorun(() => {
|
||||
const sufficientlyStableUpdateChannels = getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get());
|
||||
const updateIsDiscoveredFromChannel = discoveredVersionState.value.get()?.updateChannel;
|
||||
|
||||
setUpdateOnQuit((
|
||||
updateIsDiscoveredFromChannel
|
||||
? sufficientlyStableUpdateChannels.includes(updateIsDiscoveredFromChannel.id)
|
||||
: false
|
||||
));
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): ReleaseChannel[] => {
|
||||
if (!updateChannel.moreStableUpdateChannel) {
|
||||
return [updateChannel.id];
|
||||
}
|
||||
|
||||
return [
|
||||
updateChannel.id,
|
||||
...getSufficientlyStableUpdateChannels(updateChannel.moreStableUpdateChannel),
|
||||
];
|
||||
};
|
||||
|
||||
export default watchIfUpdateShouldHappenOnQuitInjectable;
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { restartAndInstallUpdateChannel } from "../common/restart-and-install-update-channel";
|
||||
import messageToChannelInjectable from "../../../renderer/utils/channel/message-to-channel.injectable";
|
||||
|
||||
const restartAndInstallUpdateInjectable = getInjectable({
|
||||
id: "restart-and-install-update",
|
||||
|
||||
instantiate: (di) => {
|
||||
const messageToChannel = di.inject(messageToChannelInjectable);
|
||||
|
||||
return () => {
|
||||
messageToChannel(restartAndInstallUpdateChannel);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default restartAndInstallUpdateInjectable;
|
||||
Reference in new issue
Block a user