Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions TESTS/MIDI_management/creatingNoteEvents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ test("Testing: createNoteEvents", () =>{
// DELETED DURING DEVELOPMENT CAUSE TAKES TO MUCH TIME
//

describe("Testing: AnimationFrameMidiPlayer", () =>{
const onEvent = (data) =>{
}
const note_events = createNoteEvents(MIDI_mock,timeSignatures(MIDI_mock))
const player = new AnimationFrameMidiPlayer(note_events, onEvent);
player.pausePlay()
it("resolve in 10m seconds",async () =>{
const result = await player.__for_testing()
expect(result).toBe(true)
}, player.MidiLength + 1000)
})
// describe("Testing: AnimationFrameMidiPlayer", () =>{
// const onEvent = (data) =>{
// }
// const note_events = createNoteEvents(MIDI_mock,timeSignatures(MIDI_mock))
// const player = new AnimationFrameMidiPlayer(note_events, onEvent);
// player.pausePlay()
// it("resolve in 10m seconds",async () =>{
// const result = await player.__for_testing()
// expect(result).toBe(true)
// }, player.MidiLength + 1000)
// })
19 changes: 19 additions & 0 deletions TESTS/OTHER/About.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { expect, it, describe} from "vitest";
import { render, screen } from '@testing-library/react';
import userEvent from "@testing-library/user-event";

import FAQ_component from "../../src/Pages/About/FAQ/FAQ.tsx";
import questions from "../../src/Utils/FAQ_questions";

describe("FAQ questions rendering",()=>{
it("should render exact number of questions", () =>{
render(<FAQ_component questions={questions}/>);
expect(screen.getByTestId("FAQ_container_for_questions").children.length).toEqual(questions.length);
});
it("should change class on click", async () =>{
render(<FAQ_component questions={questions}/>);
const element = screen.getByTestId("FAQ_container_for_questions").children[0]
await userEvent.click(element);
expect(element.classList).toContain("FAQ_open");
})
})
5 changes: 5 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import PlayLive from './Pages/PlayLive/PlayLive';
import {Routes as Switch, Route} from 'react-router-dom';
import './App.css';

/**
* Main App function with router.
* Here add new routes
* @returns
*/
function App() {

return (
Expand Down
6 changes: 4 additions & 2 deletions src/Components/DonationPrompt/DonationPrompt.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React,{useEffect,useState} from 'react'
import DonateButton from '../DonateButton/DonateButton';
import Hi from '../../Assets/hi.png';
import './DonationPrompt.scss'

/**
* @deprecated
* @returns
*/
export default function DonationPrompt() {

const [canPrompt,setCanPrompt] = useState<boolean>(false);
Expand All @@ -25,7 +28,6 @@ export default function DonationPrompt() {
If you like using this app consider donating
It really helps run this project for free
</h4>
<DonateButton className='DonBut' link='https://www.paypal.com/donate/?hosted_button_id=TLEW452UQRPFG'/>
<h2>Thank You!</h2>
<button onClick={()=>{setCanPrompt(false)}}>Close</button>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/Components/DrawPiano/LoadingScreen/LoadingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import React,{ReactElement,useState,useEffect} from 'react'
import './LoadingScreen.scss';
import PBA_Icon from "../../../Assets/PBA_logo.png"
interface LoadingScreenProps{
Finished:boolean
}
Expand All @@ -34,7 +35,7 @@ export default function LoadingScreen({Finished}:LoadingScreenProps):ReactElemen
return (
<>
{render_screen && <div className='LoadingScreen' style={{opacity:opacity.toString()}}>
<img src={'/PBA_logo.png'} alt='Loading' />
<img src={PBA_Icon} alt='Loading' />
<div className='LoadingText'>
<h2 className='jersey-10'>Reading the MIDI file, please wait...</h2>
<div className='traveler'>
Expand Down
36 changes: 14 additions & 22 deletions src/Components/DrawPiano/UpdatedDrawPiano.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
/**
* Component Created during new ver creation for AVANT
* Last Update: 07/29/2025
* Last Update: 12/09/2025
* - Component is a refreshed version of "DrawPiano", which can handle new, not obesolete components
* - Component now should be able to handle different height and width, not only fixed to window Size
* - Moved Loading Screen Here
* - Moved Watermark render Here
*/

import React, {useEffect, useState } from "react";
import AnimationFrameMidiPlayer from "../../Helpers/MidiReader/AnimationFrameMidiPlayer";
import { TrackNoteEvent } from "../../Utils/TypesForMidi";
import LoadingScreen from "./LoadingScreen/LoadingScreen";
import soundManagerClass from "../../Helpers/soundManager";
import { useSelector } from 'react-redux';
Expand All @@ -36,51 +34,45 @@ export default function UpdatedDrawPiano({width,height,Player,piano_keys_height

const nr_of_white_keys = total_nr_of_keys === 25 ? 15 : total_nr_of_keys === 49 ? 28 : total_nr_of_keys === 61 ? 36 : total_nr_of_keys === 76 ? 44 : 52; //I don't believe I had to write this...
const [is_loading,set_is_loading] = useState<boolean>(true);
const [soundManager,setSoundManager] = useState<soundManagerClass>();
const [soundManager,setSoundManager] = useState<soundManagerClass | null>(null);
const options = useSelector((state:{options:OptionsType}) => state.options);

//If player and sounds are ready, then set the loading screen to dissapear
useEffect(()=>{
if(Player && soundManager){
soundManager.load_sounds().then(e => set_is_loading(false));
if(Player){
if(options.soundOn === true){
if(soundManager)soundManager.load_sounds().then(e => set_is_loading(false));
return;
}
//else
set_is_loading(false);
}
},[Player, soundManager])

//When player is ready and maxvelocity can be deducted, create sound manager
useEffect(()=>{
if(Player){
if(Player && options.soundOn === true){
setSoundManager(new soundManagerClass(Player.MidiMaxVelocity * 50))
}
},[Player])

//Function renders the tracks only when player is defined, and sounds are defined (if sounds are on)
const renderTracks = ():React.ReactElement =>{
if(Player !== undefined && soundManager !== undefined){
if(Player !== undefined && (soundManager !== undefined || options.soundOn === false)){
return <Tracks
Player={Player}
height={height}
width={width}
number_of_white_keys={nr_of_white_keys}
white_key_height={piano_keys_height}
options={options}
sound={soundManager}
number_of_keys={total_nr_of_keys}
/>
}
return <></>
}

const renderWatermark = ():React.ReactElement => {
if(options.watermark){
return (
<div className="Watermark">
<h3>Some watermark</h3>
</div>)
}
return <></>
}


return <div className="Piano" style={{width:width, height:height}}>
<LoadingScreen Finished={!is_loading}/> {/*Loading Screen will automatically dissapear after it's work is done, so this will become an empty component*/}
{renderTracks()}
{renderWatermark()}
</div>
}
27 changes: 16 additions & 11 deletions src/Components/PlayingManagement/UpdatedPlayingManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,30 @@ interface UPM_props{
/**
* Component handles the bar with "pause,play,stop,reset,move" etc.
* Important for user interaction and control of what is goind on with the playing
* @param param0
* @returns
* @param Player AnimationFrameMidiPlayer needed to run the component, as all the buttons correspond with it
*/
export default function UpdatedPlayingManagement({Player}:UPM_props):React.ReactElement {

const timeout_ref = useRef<any>(null);
const [dot_left,set_dot_left] = useState<number>(0);
const [bt_display,set_bt_display] = useState<string>(Button_Play);
const [timing, set_timing] = useState<{curr:number,length:number}>({curr:0,length:0});
const [active, setActive] = useState<boolean>(false);
const navi = useNavigate();
const timeout_ref = useRef<any>(null); //auto hide the element
const [dot_left,set_dot_left] = useState<number>(0); //for playing bar, how much % of was played
const [bt_display,set_bt_display] = useState<string>(Button_Play); //paused or played button to display
const [timing, set_timing] = useState<{curr:number,length:number}>({curr:0,length:0}); //time of playing
const [active, setActive] = useState<boolean>(false); //is bar visible
const navi = useNavigate(); //navigate to go back to main page

//Handle pause play...
const handlePausePlay = ():void =>{
Player.pausePlay();
set_bt_display(curr => curr === Button_Play ? Button_Pause : Button_Play)
}

//Handle Reset of the playing...
const handleResetButton = ():void =>{
Player.restart();
set_bt_display(Button_Play)
set_bt_display(Button_Play);
}

//When Player is ready, set function to handle update of the timer every 100ms
useEffect(()=>{
if(Player){
const handle_timer_update = ():void =>{
Expand All @@ -51,7 +53,8 @@ export default function UpdatedPlayingManagement({Player}:UPM_props):React.React
}
},[Player])

const make_timer_string = () =>{
//Function to create the timer of how much of the track was played
const make_timer_string = ():string =>{
let curr_str, length_str
const mins = Math.floor(timing.curr/60)
const secs = Math.floor(timing.curr % 60);
Expand All @@ -62,13 +65,14 @@ export default function UpdatedPlayingManagement({Player}:UPM_props):React.React
return curr_str + "/" + length_str
}

//handle clicking on the bar
const click_bar_handler = (ev:MouseEvent) =>{
const target_data = ev.currentTarget.getBoundingClientRect()
const percent = Math.floor((ev.clientX - target_data.x) *100 /target_data.width);
Player.moveTo(percent + 1);
}


//set player active on mouse move
const set_player_active = ():void =>{
if(active === false){
setActive(true);
Expand All @@ -79,6 +83,7 @@ export default function UpdatedPlayingManagement({Player}:UPM_props):React.React
},2000);
}


useEffect(()=>{
window.addEventListener('mousemove',set_player_active);
return () => {window.removeEventListener('mousemove',set_player_active)}
Expand Down
12 changes: 5 additions & 7 deletions src/Components/Preview/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import React, {useState, useEffect, useCallback, useRef} from 'react'
import './Preview.scss'

import UpdatedTracks from '../Tracks/updatedTracks'
import LoadingScreen from '../DrawPiano/LoadingScreen/LoadingScreen'
import AnimationFrameMidiPlayer from '../../Helpers/MidiReader/AnimationFrameMidiPlayer'
import { TrackNoteEvent } from '../../Utils/TypesForMidi'
import { Options as OptionsType } from '../../Utils/TypesForOptions';
import { useSelector } from 'react-redux';

Expand All @@ -14,12 +12,12 @@ interface PrevProps{

/**
* Preview component creates a small piano, to preview the changes done in options
* LAST EDIT: 12/09/2025
* @param active As preview is designed for OptionsTab, which can be either open, or closed, this parameter defines if preview should be rendered
* @returns
*/
export default function Preview({active}:PrevProps):React.ReactElement {

const [events, setEvents] = useState<TrackNoteEvent[]>([]);
const [player, setPlayer] = useState<AnimationFrameMidiPlayer>();
const [key, addKey] = useState<number>(0);
const [ready,setReady] = useState<boolean>(false);
Expand All @@ -29,12 +27,12 @@ export default function Preview({active}:PrevProps):React.ReactElement {
const timeout_ref = useRef<any>(0);

/**
* Load the component
* Load the component, loaded the player when it is undefined.
*/
useEffect(()=>{
if(player === undefined && width_ref.current !== null){
const props = width_ref.current.getBoundingClientRect();
setPlayer(new AnimationFrameMidiPlayer([],setEvents))
setPlayer(new AnimationFrameMidiPlayer([]))
//Set width and height initially
set_width_height({
width: props.width,
Expand Down Expand Up @@ -85,6 +83,7 @@ export default function Preview({active}:PrevProps):React.ReactElement {
}
},[active])

//Set new width and height on resize
const listener = useCallback(()=>{
if(width_ref.current === null)return;
const props = width_ref.current.getBoundingClientRect();
Expand All @@ -95,6 +94,7 @@ export default function Preview({active}:PrevProps):React.ReactElement {
},[width_ref.current])


//Add listeners for resize
useEffect(()=>{
window.addEventListener('resize',listener)

Expand All @@ -112,11 +112,9 @@ export default function Preview({active}:PrevProps):React.ReactElement {
Player={player}
height={width_height.height + 200}
width={width_height.width}
number_of_keys={width_height.width > 760 ? 76 : 25}
number_of_white_keys={width_height.width > 760 ? 44 : 15}
options={options}
sound={null}
white_key_height={400}
/>}
</div>}
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/Components/Tracks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//!! FILE DEPRECATED

import TracksAnimationFrame from './Tracks';
import TracksInterval from './TracksIntervalMethod';

Expand Down
Loading