Commit Graph

29 Commits

Author SHA1 Message Date
undergroundwires
8ccaec7af6 Fix unresponsive copy button on instructions modal
This commit fixes the bug where the "Copy" button does not copy when
clicked on download instructions modal (on Linux and macOS).

This commit also introduces several improvements to the UI components
related to copy action and their interaction with the clipboard feature.

It adds more tests to avoid regression of the bugs and improves
maintainability, testability and adherence to Vue's reactive principles.

Changes include:

- Fix non-responsive copy button in the download instructions modal by
  triggering a `click` event in `AppIcon.vue`.
- Improve `TheCodeButtons.vue`:
  - Remove redundant `getCurrentCode` function.
  - Separate components for each button for better separation of
    concerns and higher testability.
  - Use the `gap` property in the flexbox layout, replacing the less
    explicit sibling combinator approach.
- Add `useClipboard` compositional hook for more idiomatic Vue approach
  to interacting with the clipboard.
- Add `useCurrentCode` compositional hook to handle current code state
  more effectively with unified logic.
- Abstract clipboard operations to an interface to isolate
  responsibilities.
- Switch clipboard implementation to the `navigator.clipboard` API,
  moving away from the deprecated `document.execCommand`.
- Move clipboard logic to the presentation layer to conform to
  separation of concerns and domain-driven design principles.
- Improve `IconButton.vue` component to increase reusability with
  consistent sizing.
2023-11-06 21:55:43 +01:00
undergroundwires
ca81f68ff1 Migrate to Vue 3.0 #230
- Migrate from "Vue 2.X" to "Vue 3.X"
- Migrate from "Vue Test Utils v1" to "Vue Test Utils v2"

Changes in detail:

- Change `inserted` to `mounted`.
- Change `::v-deep` to `:deep`.
- Change to Vue 3.0 `v-modal` syntax.
- Remove old Vue 2.0 transition name, keep the ones for Vue 3.0.
- Use new global mounting API `createApp`.
- Change `destroy` to `unmount`.
- Bootstrapping:
  - Move `provide`s for global dependencies to a bootsrapper from
    `App.vue`.
  - Remove `productionTip` setting (not in Vue 3).
  - Change `IVueBootstrapper` for simplicity and Vue 3 compatible API.
  - Add missing tests.
- Remove `.text` access on `VNode` as it's now internal API of Vue.
- Import `CSSProperties` from `vue` instead of `jsx` package.
- Shims:
  - Remove unused `shims-tsx.d.ts`.
  - Remove `shims-vue.d.ts` that's missing in quickstart template.
- Unit tests:
  - Remove old typing workaround for mounting components.
  - Rename `propsData` to `props`.
  - Remove unneeded `any` cast workarounds.
  - Move stubs and `provide`s under `global` object.

Other changes:

- Add `dmg-license` dependency explicitly due to failing electron builds
  on macOS (electron-userland/electron-builder#6520,
  electron-userland/electron-builder#6489). This was a side-effect of
  updating dependencies for this commit.
2023-11-01 13:39:39 +01:00
undergroundwires
4995e49c46 Improve UI performance by optimizing reactivity
- Replace `ref`s with `shallowRef` when deep reactivity is not needed.
- Replace `readonly`s with `shallowReadonly` where the goal is to only
  prevent `.value` mutation.
- Remove redundant `ref` in `SizeObserver.vue`.
- Remove redundant nested `ref` in `TooltipWrapper.vue`.
- Remove redundant `events` export from `UseCollectionState.ts`.
- Remove redundant `computed` from `UseCollectionState.ts`.
- Remove `timestamp` from `TreeViewFilterEvent` that becomes unnecessary
  after using `shallowRef`.
- Add missing unit tests for `UseTreeViewFilterEvent`.
- Add missing stub for `FilterChangeDetails`.
2023-10-31 13:57:57 +01:00
undergroundwires
f8e5f1a5a2 Fix incorrect tooltip position after window resize
This commit fixes an issue where the tooltip position becomes inaccurate
after resizing the window.

The solution uses `autoUpdate` functionality of `floating-ui` to update
the position automatically on resize events. This function depends on
browser APIs: `IntersectionObserver` and `ResizeObserver`. The official
documentation recommends polyfilling those to support old browsers.

Polyfilling `ResizeObserver` is already part of the codebase, used by
`SizeObserver.vue`. This commit refactors polyfill logic to be reusable
across different components, and reuses it on `TooltipWrapper.vue`.

Polyfilling `IntersectionObserver` is ignored due to this API being
older and more widely supported.
2023-10-27 20:58:07 +02:00
undergroundwires
48730bca05 Implement new UI component for icons #230
- Introduce `AppIcon.vue`, offering improved performance over the
  previous `fort-awesome` dependency. This implementation reduces bundle
  size by 67.31KB (tested for web using `npm run build -- --mode prod`).
- Migrate Font Awesome 5 icons to Font Awesome 6.

This commit facilitates migration to Vue 3.0 (#230) and ensures no Vue
component remains tightly bound to a specific Vue version, enhancing
code portability.

Font Awesome license is not included because Font Awesome revokes its
right:

> "Attribution is no longer required as of Font Awesome 3.0"
>
> Sources:
>
> - https://fontawesome.com/v4/license/ (archived: https://web.archive.org/web/20231003213441/https://fontawesome.com/v4/license/, https://archive.ph/Yy9j5)
> - https://github.com/FortAwesome/Font-Awesome/wiki (archived: https://web.archive.org/web/20231003214646/https://github.com/FortAwesome/Font-Awesome/wiki, https://archive.ph/C6sXv)

This commit removes following third-party production dependencies:

- `@fortawesome/vue-fontawesome`
- `@fortawesome/free-solid-svg-icons`
- `@fortawesome/free-regular-svg-icons`
- `@fortawesome/free-brands-svg-icons`
- `@fortawesome/fontawesome-svg-core`
2023-10-11 18:38:19 +02:00
undergroundwires
8b930fc57c Rewrite tooltip UI for efficiency and Vue 3.0 #230
- Introduce a new UI component for tooltips.
- Fix tooltip arrow misalignment issues in code download/execution
  instructions dialogs.

Reasons for dropping `v-tooltip` dependency:

- Lack of support for Vue 3.0, which blocks migration to Vue 3.0 (see
  #230).
- Inability to render HTML content that's required for privacy.sexy.
- Inefficient, adding an extra 162.48 KB to the production bundle for
  web distribution (tested using `npm run build -- --mode production`).

Advantages of adopting `floating-ui` (Floating UI):

- Compatibility across multiple Vue versions including 2.0, 2.7, and 3.0.
- Reduced boilerplate resulting in cleaner, more maintainable code.
- Efficient position recalculations without reinventing the wheel.
2023-09-18 17:57:50 +02:00
undergroundwires
eb096d07e2 Fix memory leaks via auto-unsubscribing and DI
This commit simplifies event handling, providing a unified and robust
way to handle event lifecycling. This way, it fixes events not being
unsubscribed when state is changed.

Introduce a new function in `EventSubscriptionCollection` to remove
existing events and adding new events. This provides an easier to use
API, which leads to code that's easier to understand. It also prevents
potential bugs that may occur due to forgetting to call both functions.
It fixes `TheScriptsMenu` not unregistering events on state change.
Other improvements include:
  - Include a getter to get total amount of registered subcriptions.
    This helps in unit testing.
  - Have nullish checks to prevent potential errors further down the
    execution.
  - Use array instead of rest parameters to increase readability and
    simplify tests.

Ensure `SliderHandler` stops resizes on unmount, unsubscribing from all
events and resetting state to default.

Update `injectionKeys` to do imports as types to avoid circular
dependencies. Simplify importing `injectionKeys` to enable and strict
typings for iterating injection keys.

Add tests covering new behavior.
2023-09-01 18:14:25 +02:00
undergroundwires
ad0576a752 Improve desktop runtime execution tests
Test improvements:

- Capture titles for all macOS windows, not just the frontmost.
- Incorporate missing application log files.
- Improve log clarity with enriched context.
- Improve application termination on macOS by reducing grace period.
- Ensure complete application termination on macOS.
- Validate Vue application loading through an initial log.
- Support ignoring environment-specific `stderr` errors.
- Do not fail the test if working directory cannot be deleted.
- Use retry pattern when installing dependencies due to network errors.

Refactorings:

- Migrate the test code to TypeScript.
- Replace deprecated `rmdir` with `rm` for error-resistant directory
  removal.
- Improve sanity checking by shifting from App.vue to Vue bootstrapper.
- Centralize environment variable management with `EnvironmentVariables`
  construct.
- Rename infrastructure/Environment to RuntimeEnvironment for clarity.
- Isolate WindowVariables and SystemOperations from RuntimeEnvironment.
- Inject logging via preloader.
- Correct mislabeled RuntimeSanity tests.

Configuration:

- Introduce `npm run check:desktop` for simplified execution.
- Omit `console.log` override due to `nodeIntegration` restrictions and
  reveal logging functionality using context-bridging.
2023-08-29 16:30:00 +02:00
undergroundwires
e9e0001ef8 Improve desktop security by isolating Electron
Enable `contextIsolation` in Electron to securely expose a limited set
of Node.js APIs to the renderer process. It:

1. Isolates renderer and main process contexts. It ensures that the
   powerful main process functions aren't directly accessible from
   renderer process(es), adding a security boundary.
2. Mitigates remote exploitation risks. By isolating contexts, potential
   malicious code injections in the renderer can't directly reach and
   compromise the main process.
3. Reduces attack surface.
4. Protect against prototype pollution: It prevents tampering of
   JavaScript object prototypes in one context from affecting another
   context, improving app reliability and security.

Supporting changes include:

- Extract environment and system operations classes to the infrastructure
  layer. This removes node dependencies from core domain and application
  code.
- Introduce `ISystemOperations` to encapsulate OS interactions. Use it
  from `CodeRunner` to isolate node API usage.
- Add a preloader script to inject validated environment variables into
  renderer context. This keeps Electron integration details
  encapsulated.
- Add new sanity check to fail fast on issues with preloader injected
  variables.
- Improve test coverage of runtime sanity checks and environment
  components. Move validation logic into separate classes for Single
  Responsibility.
- Improve absent value test case generation.
2023-08-25 14:31:30 +02:00
undergroundwires
62f8bfac2f Fix searching/filtering bugs #235
- Fix a bug (introduced in 1b9be8fe) preventing the tree view from being
  visible during a search.
- Fix a minor bug where the scripts view does not render based on the
  initial filter.
- Add Vue component tests for `TheScriptView` to prevent regressions.
- Refactor `isSearching` in `TheScriptView` to simplify its logic.
2023-08-25 00:32:01 +02:00
undergroundwires
ae75059cc1 Increase testability through dependency injection
- Remove existing integration tests for hooks as they're redundant after
  this change.
- Document the pattern in relevant documentation.
- Introduce `useEnvironment` to increase testability.
- Update components to inject dependencies rather than importing hooks
  directly.
2023-08-15 18:11:30 +02:00
undergroundwires
bc91237d7c Refactor usage of tooltips for flexibility
This commit introduces a new Vue component to handle tooltips. It acts
as a wrapper for the `v-tooltip`. It enhances the maintainability,
readability and portability of tooltips by enabling the direct inclusion
of inline HTML in the tooltip components. It solves issues such as
absence of linting or editor support and cumbersome string
concatenation.

It also provides an abstraction layer that simplifies the switching
between different tooltip implementations, which would allow a smooth
migration to Vue 3 (see #230).
2023-08-12 16:53:58 +02:00
undergroundwires
9e5491fdbf Implement custom lightweight modal #230
Introduce a brand new lightweight and efficient modal component. It is
designed to be visually similar to the previous one to not introduce a
change in feel of the application in a patch release, but behind the
scenes it features:

- Enhanced application speed and reduced bundle size.
- New flexbox-driven layout, eliminating JS calculations.
- Composition API ready for Vue 3.0 #230.

Other changes:

- Adopt idiomatic Vue via `v-modal` binding.
- Add unit tests for both the modal and dialog.
- Remove `vue-js-modal` dependency in favor of the new implementation.
- Adjust modal shadow color to better match theme.
- Add `@vue/test-utils` for unit testing.
2023-08-11 19:35:26 +02:00
undergroundwires
1b9be8fe2d Refactor Vue components using Composition API #230
- Migrate `StatefulVue`:
  - Introduce `UseCollectionState` that replaces its behavior and acts
    as a shared state store.
  - Add more encapsulated, granular functions based on read or write
    access to state in CollectionState.
- Some linting rules get activates due to new code-base compability to
  modern parses, fix linting errors.
  - Rename Dialog to ModalDialog as after refactoring,
    eslintvue/no-reserved-component-names does not allow name Dialog.
  - To comply with `vue/multi-word-component-names`, rename:
    - `Code`          -> `CodeInstruction`
    - `Handle`        -> `SliderHandle`
    - `Documentable`  -> `DocumentableNode`
    - `Node`          -> `NodeContent`
    - `INode`         -> `INodeContent`
    - `Responsive`    -> `SizeObserver`
- Remove `vue-property-decorator` and `vue-class-component`
  dependencies.
- Refactor `watch` with computed properties when possible for cleaner
  code.
  - Introduce `UseApplication` to reduce repeated code in new components
    that use `computed` more heavily than before.
- Change TypeScript target to `es2017` to allow top level async calls
  for getting application context/state/instance to simplify the code by
  removing async calls. However, mocha (unit and integration) tests do
  not run with top level awaits, so a workaround is used.
2023-08-07 13:16:39 +02:00
undergroundwires
ff84f5676e Transition to eslint-config-airbnb-with-typescript
- Migrate to newer `eslint-config-airbnb-with-typescript` from
  `eslint-config-airbnb`.
- Add also `rushstack/eslint-patch` as per instructed by
  `eslint-config-airbnb-with-typescript` docs.
- Update codebase to align with new linting standards.
- Add script to configure VS Code for effective linting for project
  developers, move it to `scripts` directory along with clean npm
  install script for better organization.
2023-08-04 16:39:36 +02:00
undergroundwires
7d3670c26d Improve manual execution instructions
- Simplify alternatives to run the script.
- Change style of code parts to be easier to the eye:
  - Use the same font size as other texts in body.
  - Add vertical padding.
  - Align the contents (the code, copy button and dollar sign) in the
    middle.
  - Align information icon to center of context next to it.
- Fix minor typos and punctations.
- Refactor instruction list to be more generic to able to be used by
  other operating systems.
- Make dialogs scrollable so instruction list on smaller screens can be
  read until the end.
2022-10-01 19:50:45 +02:00
undergroundwires
3233d9b802 Improve click/touch without unintended interaction
Disable selecting clickables as text. Selecting buttons leads to
unintended selection. This is seen when touching on clickables using
mobile devices.

Prevent blue highlight when touching on clickables. This is seen on
mobile webkit browsers. It looks ugly and the visual clue provided is
not needed beacuse all clickables on mobile already  have visual clues.
2022-03-13 12:45:17 +01:00
undergroundwires
99e24b4134 Improve touch like hover on devices without mouse
This commit improves mobile support. `:hover` CSS selector is not mobile
friendly because there is typically no mouse support on mobile. This
commit make hover behavior to become active during touch on mobile.

`:hover` selector is emulated on mobile devices. But this emulated
behavior is not desired. When emulated, the CSS style gets attached when
starting touching but does not get removed after stopping touching. This
sticky behavior is undesired.

This commit solve this issue by using Saas mixing that uses `:active`
selector instead of `:hover` when `:hover` is not really supported but
emulated.
2022-03-12 10:59:28 +01:00
undergroundwires
44d79e2c9a Add more and unify tests for absent object cases
- Unify test data for nonexistence of an object/string and collection.
- Introduce more test through adding missing test data to existing tests.
- Improve logic for checking absence of values to match tests.
- Add missing tests for absent value validation.
- Update documentation to include shared test functionality.
2022-01-21 22:34:11 +01:00
undergroundwires
5b1fbe1e2f Refactor code to comply with ESLint rules
Major refactoring using ESLint with rules from AirBnb and Vue.

Enable most of the ESLint rules and do necessary linting in the code.
Also add more information for rules that are disabled to describe what
they are and why they are disabled.

Allow logging (`console.log`) in test files, and in development mode
(e.g. when working with `npm run serve`), but disable it when
environment is production (as pre-configured by Vue). Also add flag
(`--mode production`) in `lint:eslint` command so production linting is
executed earlier in lifecycle.

Disable rules that requires a separate work. Such as ESLint rules that
are broken in TypeScript: no-useless-constructor (eslint/eslint#14118)
and no-shadow (eslint/eslint#13014).
2022-01-02 18:20:14 +01:00
undergroundwires
c3c5b897f3 Refactor to add readonly interfaces
Using more granular interfaces adds to expressiveness of the code.
Knowing what needs to mutate the state explicitly helps easier
understanding of the code and therefore increases the maintainability.
2021-12-24 21:14:27 +01:00
undergroundwires
bf83c58982 Refactor Saas naming, structure and modules
- Add more documentation.
- Use `main.scss` instead of importing components individually. This
  improves productivity without compilation errors due to missing
  imports and allows for easier future file/folder changes and
  refactorings inside `./styles`.
- Use partials with underscored naming. Because it documents that the
  files should not be individually imported.
- Introduce `third-party-extensions` folder to group styles that
  overwrites third party components.
- Refactor variable names from generic to specific.
- Use Sass modules (`@use` and `@forward`) over depreciated `@import`
  syntax.
- Separate font assets from Sass files (`styles/`). Create `assets/`
  folder that will contain both.
- Create `_globals.css` for global styling of common element instead of
  using `App.vue`.
2021-11-14 17:48:49 +01:00
undergroundwires
82c43ba2e3 Refactor to remove "Async" function name suffix
Remove convention where Async suffix is added to functions that returns
a Promise. It was a habit from C#, but is not widely used in JavaScript
/ TypeScript world, also bloats the code. The code is more consistent
with third party dependencies/frameworks without the suffix.
2021-11-01 19:02:22 +01:00
undergroundwires
b08a6b5cec Use a consistent color system
1. Renames color names in palette. Using names such as "primary" and
"secondary" that are in consistent with designs such as material,
bootstrap and metro UI palettes. It adds `color-` prefix on color
variables in line with Vue Design System.
2. Introduces necessary changes to follow the system color system
   everywhere without using any other color:
     - It changes tooltip background from black to darker primary
     colors.
     - It overrides unset styles from tree component
     - It ensures footer has same color as top menu.
3. Removes opacity CSS changes to have better control on choices. To
   achieve that:
     - It introduces new "light" variants of main colors
     - It switches to colors with different variants (e.g. in Dialogs it
       uses primary color as button as it has variants that can be
       activated on hover meanwhile on-surface color is single).
4. Styles a tags (anchor elements) globally for consistency
2021-10-11 19:33:34 +02:00
undergroundwires
448e378dc4 increase performance by polyfilling ResizeObserver only if required 2021-03-25 13:24:19 +01:00
undergroundwires
6f46cdb4ed refactor all modals to use same dialog component 2021-03-20 16:13:25 +01:00
undergroundwires
1935db1019 fix throttle function not being able to run with argument(s) 2021-03-13 12:54:13 +01:00
undergroundwires
1f515e7be5 bump dependencies to latest
- fix npm vulnerabilities #62
- change ResizeObserver polyfill dependency que-etc/resize-observer-polyfill#80
- bump typescript to 4.2.x and add tslib for importing helpers
- update electron to v12.x and set contextIsolation to false (nklayman/vue-cli-plugin-electron-builder#1285, electron/electron#11608) to reach node APIs as it's now disabled by default (electron/electron#27949)
2021-03-11 14:50:35 +01:00
undergroundwires
f3c7413f52 restructure presentation layer
- Move most GUI related code to /presentation
- Move components to /components (separate from bootstrap and style)
- Move shared components helpers to /components/shared
- Rename Bootstrapping to bootstrapping to enforce same naming
  convention in /presentation
2021-03-07 19:37:54 +01:00