Skip to content

Technical Breakdown

Zane Helton edited this page Aug 15, 2022 · 16 revisions

What is this?

If you want to understand the codebase, read on...

The React Frontend

All of the piano logic is done within React. Rust handles our MIDI connections. Piano Trainer is heavily reliant on react-piano which has helpful functions within MidiNumbers.js (ex. .fromNote(...) and .getAttributes(...))

Everything starts in ./src/App.tsx where we return all of the UI contents. These are the top-level components that store the state data:

  • KVProvider: Key-value Provider. This is responsible for storing settings persistently and managing the setting states
  • SidebarProvider: Simple wrapper to allow any component to open/close the sidebar
  • TrainerProvider: Contains information about what's being practiced. Also handles logic for incrementing notes
  • ScreenManager: Simple wrapper to switch between practice mode and quiz mode

Within that, here are the main components of the UI:

  • Keyboard: The on-screen keyboard at the bottom. Responsible for playing piano sound and mouse input. Also handles MIDI input
  • TrainerPiano: The on-screen keyboard at the top. Responsible for highlighting the activeNotes to the user
  • Quiz: The quiz screen. All of the question generation logic is in here for now
    • QuizOption: The quiz answer choices
  • SettingsSidebar: Displays all of the Settings within the sidebar as a SettingRow
    • SettingRow: Displays either a checkbox or dropdown and a label for the setting
  • SoundfontProvider: Loads a Soundfound and allows for playback
  • TrainerDisplay: Contains the Scale & Mode dropdowns as well as ping-pong mode, etc.

Translations (i18next)

All of the on-screen text is being tracked in ./src/i18n/ to translate components. Use en.ts where applicable.

Rust Backend

Tauri apps are built on Rust. There are only a handful of important notes here as most of the logic is in React.

  • Load tauri-plugin-store to create a Store. It's a JSON file called .settings.dat which persistently stores user settings (mute sound, disable crash reports, etc.)
  • We load sentry-tauri into the Tauri app. It adds crash reports via Sentry
    • I'm using a custom branch for sentry-tauri that checks if crash reporting is disabled in .settings.dat before loading Sentry
  • Create a MidiState that's managed by Tauri. This contains the active MIDI connection
  • Create 2 functions: open_midi_connection and list_midi_connections that can be used in React
    • open_midi_connection: Creates a MIDI connection at a specified index and stores it in MidiState
    • list_midi_connections: Returns a HashMap of port names and their respective index
  • Run the app

That's it! To start running the program locally, read the development guide here.

The start-dev.sh script is only tested on macOS. On Windows, you can use yarn tauri dev instead.

Clone this wiki locally