Files
privacy.sexy/docs/presentation.md
undergroundwires 311fcb1813 Improve UI code styling for all platforms
This commit standardizes the visual styling of inline code and code
blocks, ensuring consistency across macOS, Android, Linux and Windows
platforms.

The discrepancies observed in font rendering on macOS, which caused the
inline code font to appear larger, have been addressed. This behavior
was only observed on macOS using different browsers such as Firefox,
Safari, Chromium-based browsers including Electron.

Key changes:

- Standardize font size relative to the parent element.
- Remove font-weight for uniformity, especially when the specific weight
  is not included with the application.
- Add a consistent background color to inline codes, aligning their look
  with code blocks.
- Refactor code styling into a separate SCSS file for improved
  modularity and maintainability.
- Update the documentation to reflect these visual design choices for
  privacy.sexy's UI.

These changes enhance the overall user experience by providing a
consistent look and feel for code elements within the UI, regardless of
the user's platform or browser.
2024-02-06 12:35:51 +01:00

9.5 KiB

Presentation layer

The presentation layer handles UI concerns using Vue as JavaScript framework and Electron to provide desktop functionality.

It reflects the application state and allows user interactions to modify it. Components manage their own local UI state.

The presentation layer uses an event-driven architecture for bidirectional reactivity between the application state and UI. State change events flow bottom-up to trigger UI updates, while user events flow top-down through components, some ultimately modifying the application state.

📖 Refer to architecture.md (Layered Application) to read more about the layered architecture.

Structure

Visual design best-practices

  • Clickables: Add visual clues for clickable items. It should be as clear as possible that they're interactable at first look without hovering. They should also have different visual state when hovering/touching on them that indicates that they are being clicked, which helps with accessibility.
  • Borders: privacy.sexy prefers sharper edges in its design language.

Application data

Components (should) use UseApplication to reach the application domain to avoid parsing and compiling the application again.

Application.ts is an immutable domain model that represents application state. It includes:

You can read more about how application layer provides application data to he presentation in application.md | Application data.

Application state

This project uses a singleton instance of the application state, making it available to all Vue components.

The decision to not use third-party state management libraries like vuex or pinia was made to promote code independence and enhance portability.

Stateful components can mutate and/or react to state changes (e.g., user selection, search queries) in the ApplicationContext. Vue components import CollectionState.ts to access both the application context and the state.

UseCollectionState.ts provides several functionalities including:

  • Singleton State Instance: It creates a singleton instance of the state, which is shared across the presentation layer. The singleton instance ensures that there's a single source of truth for the application's state.
  • State Change Callback and Lifecycle Management: It offers a mechanism to register callbacks, which will be invoked when the state initializes or mutates. It ensures that components unsubscribe from state events when they are no longer in use or when ApplicationContext switches the active collection.
  • State Access and Modification: It provides functions to read and mutate for accessing and modifying the state, encapsulating the details of these operations.
  • Event Subscription Lifecycle Management: Includes an events member that simplifies state subscription lifecycle events. This ensures that components unsubscribe from state events when they are no longer in use, or when ApplicationContext switches the active collection.

📖 Refer to architecture.md | Application State for an overview of event handling and application.md | Application State for an in-depth understanding of state management in the application layer.

Dependency injections

The presentation layer uses Vue's native dependency injection system to increase testability and decouple components.

To add a new dependency:

  1. Define its symbol: Define an associated symbol for every dependency in injectionSymbols.ts. Symbols are grouped into:
    • Singletons: Shared across components, instantiated once.
    • Transients: Factories yielding a new instance on every access.
  2. Provide the dependency: Modify the provideDependencies function to include the new dependency. App.vue calls this function within its setup() hook to register the dependencies.
  3. Inject the dependency: Use injectKey to inject a dependency. Pass a selector function to injectKey that retrieves the appropriate symbol from the provided dependencies.
    • Example usage: injectKey((keys) => keys.useCollectionState);

Shared UI components

Shared UI components ensure consistency and streamline front-end development.

We use homegrown components over third-party solutions or comprehensive UI frameworks like Quasar to maintain portability and easy maintenance.

Shared components include:

Desktop builds

Desktop builds uses electron-vite to bundle the code, and electron-builder to build and publish the packages.

Host system access is strictly controlled. The preloader isolates logic that interacts with the host system. These functionalities are then securely exposed to the renderer process (Vue application) using context-bridging. ApiContextBridge.ts handles the configuration of the exposed APIs, ensuring a secure bridge between the Electron and Vue layers.

Styles

Style location

  • Global styles: The assets/styles/ directory is reserved for styles that have a broader scope, affecting multiple components or entire layouts. They are generic and should not be tightly coupled to a specific component's functionality.
  • Component-specific styles: Styles closely tied to a particular component's functionality or appearance should reside near the component they are used by. This makes it easier to locate and modify styles when working on a specific component.

Sass naming convention

  • Use lowercase for variables/functions/mixins, e.g.:
    • Variable: $variable: value;
    • Function: @function function() {}
    • Mixin: @mixin mixin() {}
  • Use - for a phrase/compound word, e.g.:
    • Variable: $some-variable: value;
    • Function: @function some-function() {}
    • Mixin: @mixin some-mixin() {}
  • Grouping and name variables from generic to specific, e.g.:
    • $border-blue, $border-blue-light, $border-blue-lightest, $border-red
    • $blue-border, $light-blue-border, $lightest-blue-border, $red-border