mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
Fixed shortcuts & replaced with pure QShortcut
This commit is contained in:
parent
6a09c0c913
commit
c89c5a975a
13
README.md
13
README.md
@ -14,7 +14,7 @@ Following are the features that currently spotube offers:
|
|||||||
- Playback control is on user's machine instead of server based
|
- Playback control is on user's machine instead of server based
|
||||||
- Small size & less data hungry
|
- Small size & less data hungry
|
||||||
- No spotify or youtube ads since it uses all public & free APIs (But it's recommended to support the creators by watching/liking/subscribing to the artists youtube channel or add as favourite track in spotify. Mostly buying spotify premium is the best way to support their valuable creations)
|
- No spotify or youtube ads since it uses all public & free APIs (But it's recommended to support the creators by watching/liking/subscribing to the artists youtube channel or add as favourite track in spotify. Mostly buying spotify premium is the best way to support their valuable creations)
|
||||||
- Lyric Seek (WIP)
|
- Lyric Seek
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@ -149,11 +149,12 @@ $ npm start
|
|||||||
There will be some glitches, lags & stuck motions because of the library Spotube is currently using under the hood. It has some issues with layouts thus sometime some contents aren't shown or overflows out of the window. But resizing the window would fix this issue. Soon there will be some updates fixing this sort of layout related problems
|
There will be some glitches, lags & stuck motions because of the library Spotube is currently using under the hood. It has some issues with layouts thus sometime some contents aren't shown or overflows out of the window. But resizing the window would fix this issue. Soon there will be some updates fixing this sort of layout related problems
|
||||||
|
|
||||||
## TODO:
|
## TODO:
|
||||||
|
- [ ] Compile, Debug & Build for **MacOS**
|
||||||
- Compile, Debug & Build for **MacOS**
|
- [x] Compile, Debug & Build for **Windows**
|
||||||
- Add seek Lyric for currently playing track
|
- [x] Add seek Lyric for currently playing track
|
||||||
- Support for playing/streaming podcasts/shows
|
- [ ] Support for playing/streaming podcasts/shows
|
||||||
- Easy installation procedure/mechanism for simplicity
|
- [ ] Easy installation procedure/mechanism for simplicity in Windows
|
||||||
|
- [ ] Artist, User & Album pages
|
||||||
|
|
||||||
## Things that don't work
|
## Things that don't work
|
||||||
- Shows & Podcasts aren't supported as it'd require premium anyway
|
- Shows & Podcasts aren't supported as it'd require premium anyway
|
||||||
|
92
src/app.tsx
92
src/app.tsx
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect, useRef } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
import { Window, hot, View, useEventHandler } from "@nodegui/react-nodegui";
|
import { Window, hot, View } from "@nodegui/react-nodegui";
|
||||||
import { QIcon, QKeyEvent, QMainWindow, QMainWindowSignals, WidgetEventTypes, WindowState } from "@nodegui/nodegui";
|
import { QIcon, QMainWindow, WidgetEventTypes, WindowState, QShortcut, QKeySequence } from "@nodegui/nodegui";
|
||||||
import { MemoryRouter } from "react-router";
|
import { MemoryRouter } from "react-router";
|
||||||
import Routes from "./routes";
|
import Routes from "./routes";
|
||||||
import { LocalStorage } from "node-localstorage";
|
import { LocalStorage } from "node-localstorage";
|
||||||
@ -22,7 +22,7 @@ export enum LocalStorageKeys {
|
|||||||
credentials = "credentials",
|
credentials = "credentials",
|
||||||
refresh_token = "refresh_token",
|
refresh_token = "refresh_token",
|
||||||
preferences = "user-preferences",
|
preferences = "user-preferences",
|
||||||
volume = "volume"
|
volume = "volume",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Credentials {
|
export interface Credentials {
|
||||||
@ -54,36 +54,6 @@ const initialCredentials: Credentials = { clientId: "", clientSecret: "" };
|
|||||||
function RootApp() {
|
function RootApp() {
|
||||||
const windowRef = useRef<QMainWindow>();
|
const windowRef = useRef<QMainWindow>();
|
||||||
const [currentTrack, setCurrentTrack] = useState<CurrentTrack>();
|
const [currentTrack, setCurrentTrack] = useState<CurrentTrack>();
|
||||||
|
|
||||||
const windowEvents = useEventHandler<QMainWindowSignals>(
|
|
||||||
{
|
|
||||||
async KeyRelease(nativeEv) {
|
|
||||||
try {
|
|
||||||
if (nativeEv) {
|
|
||||||
const event = new QKeyEvent(nativeEv);
|
|
||||||
const eventKey = event.key();
|
|
||||||
if (audioPlayer.isRunning() && currentTrack)
|
|
||||||
switch (eventKey) {
|
|
||||||
case 32: //space
|
|
||||||
(await audioPlayer.isPaused()) ? await audioPlayer.play() : await audioPlayer.pause();
|
|
||||||
break;
|
|
||||||
case 16777236: //arrow-right
|
|
||||||
(await audioPlayer.isSeekable()) && (await audioPlayer.seek(+5));
|
|
||||||
break;
|
|
||||||
case 16777234: //arrow-left
|
|
||||||
(await audioPlayer.isSeekable()) && (await audioPlayer.seek(-5));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error in window events: ", error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
[currentTrack]
|
|
||||||
);
|
|
||||||
// cache
|
// cache
|
||||||
const cachedPreferences = localStorage.getItem(LocalStorageKeys.preferences);
|
const cachedPreferences = localStorage.getItem(LocalStorageKeys.preferences);
|
||||||
const cachedCredentials = localStorage.getItem(LocalStorageKeys.credentials);
|
const cachedCredentials = localStorage.getItem(LocalStorageKeys.credentials);
|
||||||
@ -160,13 +130,67 @@ function RootApp() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
windowRef.current?.addEventListener(WidgetEventTypes.Close, onWindowClose);
|
windowRef.current?.addEventListener(WidgetEventTypes.Close, onWindowClose);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
windowRef.current?.removeEventListener(WidgetEventTypes.Close, onWindowClose);
|
windowRef.current?.removeEventListener(WidgetEventTypes.Close, onWindowClose);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
let spaceShortcut: QShortcut | null;
|
||||||
|
let rightShortcut: QShortcut | null;
|
||||||
|
let leftShortcut: QShortcut | null;
|
||||||
|
// short cut effect
|
||||||
|
useEffect(() => {
|
||||||
|
if (windowRef.current) {
|
||||||
|
spaceShortcut = new QShortcut(windowRef.current);
|
||||||
|
rightShortcut = new QShortcut(windowRef.current);
|
||||||
|
leftShortcut = new QShortcut(windowRef.current);
|
||||||
|
|
||||||
|
spaceShortcut.setKey(new QKeySequence("SPACE"));
|
||||||
|
rightShortcut.setKey(new QKeySequence("RIGHT"));
|
||||||
|
leftShortcut.setKey(new QKeySequence("LEFT"));
|
||||||
|
|
||||||
|
async function spaceAction() {
|
||||||
|
try {
|
||||||
|
currentTrack && audioPlayer.isRunning() && (await audioPlayer.isPaused()) ? await audioPlayer.play() : await audioPlayer.pause();
|
||||||
|
console.log("You pressed SPACE");
|
||||||
|
} catch (error) {
|
||||||
|
showError(error, "[Failed to play/pause audioPlayer]: ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function rightAction() {
|
||||||
|
try {
|
||||||
|
currentTrack && audioPlayer.isRunning() && (await audioPlayer.isSeekable()) && (await audioPlayer.seek(+5));
|
||||||
|
console.log("You pressed RIGHT");
|
||||||
|
} catch (error) {
|
||||||
|
showError(error, "[Failed to seek audioPlayer]: ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function leftAction() {
|
||||||
|
try {
|
||||||
|
currentTrack && audioPlayer.isRunning() && (await audioPlayer.isSeekable()) && (await audioPlayer.seek(-5));
|
||||||
|
console.log("You pressed LEFT");
|
||||||
|
} catch (error) {
|
||||||
|
showError(error, "[Failed to seek audioPlayer]: ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spaceShortcut.addEventListener("activated", spaceAction);
|
||||||
|
rightShortcut.addEventListener("activated", rightAction);
|
||||||
|
leftShortcut.addEventListener("activated", leftAction);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
spaceShortcut?.removeEventListener("activated", spaceAction);
|
||||||
|
rightShortcut?.removeEventListener("activated", rightAction);
|
||||||
|
leftShortcut?.removeEventListener("activated", leftAction);
|
||||||
|
spaceShortcut = null;
|
||||||
|
rightShortcut = null;
|
||||||
|
leftShortcut = null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Window ref={windowRef} on={windowEvents} windowState={WindowState.WindowMaximized} windowIcon={winIcon} windowTitle="Spotube" minSize={minSize}>
|
<Window ref={windowRef} windowState={WindowState.WindowMaximized} windowIcon={winIcon} windowTitle="Spotube" minSize={minSize}>
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<authContext.Provider value={{ isLoggedIn, setIsLoggedIn, access_token, setAccess_token, ...credentials, setCredentials }}>
|
<authContext.Provider value={{ isLoggedIn, setIsLoggedIn, access_token, setAccess_token, ...credentials, setCredentials }}>
|
||||||
<preferencesContext.Provider value={{ ...preferences, setPreferences }}>
|
<preferencesContext.Provider value={{ ...preferences, setPreferences }}>
|
||||||
|
Loading…
Reference in New Issue
Block a user