chore(App): bump bs-platform + use rescript (#421)
This commit is contained in:
Vendored
+1
-1
@@ -5,6 +5,6 @@
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"jaredly.reason-vscode"
|
||||
"chenglou92.rescript-vscode"
|
||||
]
|
||||
}
|
||||
|
||||
+6
-3
@@ -17,6 +17,9 @@
|
||||
],
|
||||
"suffix": ".bs.js",
|
||||
"namespace": true,
|
||||
"bs-dependencies": ["reason-react", "bs-css"],
|
||||
"refmt": 3
|
||||
}
|
||||
"bs-dependencies": [
|
||||
"@rescript/react",
|
||||
"bs-css",
|
||||
"bs-css-emotion"
|
||||
]
|
||||
}
|
||||
+7
-6
@@ -18,9 +18,9 @@
|
||||
"lint:fix:prettier": "prettier --write '**/*.{json,jsx,tsx,mjs,js,ts}'",
|
||||
"lint:es": "eslint '**/*.{js,jsx,mjs,ts,tsx}'",
|
||||
"lint:fix:es": "eslint --fix '**/*.{js,jsx,mjs,ts,tsx}'",
|
||||
"bsb": "bsb -make-world",
|
||||
"bsb:watch": "bsb -make-world -w",
|
||||
"bsb:clean": "bsb -clean-world",
|
||||
"res": "rescript build",
|
||||
"res:watch": "rescript build -w",
|
||||
"res:clean": "rescript clean",
|
||||
"dist": "yarn install && yarn build && electron-builder build --win --linux --mac --ia32 --x64",
|
||||
"dist:win": "yarn install && yarn build && electron-builder build --win --x64",
|
||||
"dist:linux": "yarn install && yarn build && electron-builder build --linux --x64",
|
||||
@@ -131,6 +131,7 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.13.13",
|
||||
"@babel/preset-env": "^7.13.12",
|
||||
"@rescript/react": "0.10.3",
|
||||
"@svgr/webpack": "5.5.0",
|
||||
"acorn-dynamic-import": "^4.0.0",
|
||||
"babel-eslint": "10.1.0",
|
||||
@@ -138,8 +139,8 @@
|
||||
"babel-loader": "8.2.2",
|
||||
"babel-plugin-named-asset-import": "^0.3.7",
|
||||
"babel-preset-react-app": "^10.0.0",
|
||||
"bs-css": "^11.0.0",
|
||||
"bs-platform": "8.4.2",
|
||||
"bs-css": "^15.3.0",
|
||||
"bs-css-emotion": "^4.3.0",
|
||||
"camelcase": "^5.2.0",
|
||||
"case-sensitive-paths-webpack-plugin": "2.3.0",
|
||||
"conventional-changelog-cli": "^2.1.1",
|
||||
@@ -170,7 +171,7 @@
|
||||
"pnp-webpack-plugin": "1.2.1",
|
||||
"prettier": "^1.18.2",
|
||||
"react-dev-utils": "^9.0.1",
|
||||
"reason-react": "^0.7.1",
|
||||
"rescript": "9.1.4",
|
||||
"resolve": "1.17.0",
|
||||
"semver": "6.0.0",
|
||||
"string-replace-loader": "^2.3.0",
|
||||
|
||||
+4
-4
@@ -51,15 +51,15 @@ const config = configFactory('production');
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => new Promise((resolve, reject) => {
|
||||
const bsb = exec('npm run bsb',
|
||||
const res = exec('npm run res',
|
||||
(err) => {
|
||||
if (err) {
|
||||
console.log("Couldn't build reason using bsb");
|
||||
console.log("Couldn't build rescript using res");
|
||||
reject(err)
|
||||
}
|
||||
});
|
||||
bsb.stdout.pipe(process.stdout)
|
||||
bsb.on('exit', resolve)
|
||||
res.stdout.pipe(process.stdout)
|
||||
res.on('exit', resolve)
|
||||
}))
|
||||
.then(() => {
|
||||
// First, read the current file sizes in build directory.
|
||||
|
||||
+4
-4
@@ -64,15 +64,15 @@ if (process.env.HOST) {
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => new Promise((resolve, reject) => {
|
||||
const bsb = exec('npm run bsb',
|
||||
const res = exec('npm run res',
|
||||
(err) => {
|
||||
if (err) {
|
||||
console.log("Couldn't build reason using bsb");
|
||||
console.log("Couldn't build rescript using rescript");
|
||||
reject(err)
|
||||
}
|
||||
});
|
||||
bsb.stdout.pipe(process.stdout)
|
||||
bsb.on('exit', resolve)
|
||||
res.stdout.pipe(process.stdout)
|
||||
res.on('exit', resolve)
|
||||
}))
|
||||
.then(() => {
|
||||
// We attempt to use the default port but if it is busy, we offer the user to
|
||||
|
||||
+29
-37
@@ -7,43 +7,36 @@ type playingState = {
|
||||
muted: bool,
|
||||
hasNext: bool,
|
||||
hasPrev: bool,
|
||||
};
|
||||
}
|
||||
|
||||
type song = {
|
||||
id: int,
|
||||
artist: string,
|
||||
title: string,
|
||||
};
|
||||
}
|
||||
|
||||
type playlistItem = {
|
||||
id: int,
|
||||
path: string,
|
||||
title: string,
|
||||
artist: string,
|
||||
};
|
||||
}
|
||||
|
||||
type playlist = array(playlistItem);
|
||||
type playlist = array<playlistItem>
|
||||
|
||||
type value = {
|
||||
playingState,
|
||||
playlist,
|
||||
playingState: playingState,
|
||||
playlist: playlist,
|
||||
playlistID: string,
|
||||
setPlaylist:
|
||||
(~beatmapPlaylist: playlist, ~playlistID: string=?, unit) => unit,
|
||||
setAudio:
|
||||
(
|
||||
~song: song,
|
||||
~audioFilePath: option(string),
|
||||
~previewOffset: option(int)
|
||||
) =>
|
||||
unit,
|
||||
setPlaylist: (~beatmapPlaylist: playlist, ~playlistID: string=?, unit) => unit,
|
||||
setAudio: (~song: song, ~audioFilePath: option<string>, ~previewOffset: option<int>) => unit,
|
||||
setVolume: float => unit,
|
||||
pause: unit => unit,
|
||||
togglePlayPause: unit => unit,
|
||||
setMuted: bool => unit,
|
||||
playNext: unit => unit,
|
||||
playPrevious: unit => unit,
|
||||
};
|
||||
}
|
||||
|
||||
let initialState: playingState = {
|
||||
artist: "",
|
||||
@@ -54,36 +47,35 @@ let initialState: playingState = {
|
||||
muted: false,
|
||||
hasNext: false,
|
||||
hasPrev: false,
|
||||
};
|
||||
}
|
||||
|
||||
module Provider = {
|
||||
let value = {
|
||||
playingState: initialState,
|
||||
playlist: [||],
|
||||
playlist: [],
|
||||
playlistID: "",
|
||||
setPlaylist: (~beatmapPlaylist: playlist, ~playlistID=?, unit) => unit,
|
||||
setAudio:
|
||||
(
|
||||
~song: song,
|
||||
~audioFilePath: option(string),
|
||||
~previewOffset: option(int),
|
||||
) =>
|
||||
(),
|
||||
setVolume: (vol: float) => (),
|
||||
setPlaylist: (~beatmapPlaylist as _: playlist, ~playlistID as _=?, unit) => unit,
|
||||
setAudio: (
|
||||
~song as _: song,
|
||||
~audioFilePath as _: option<string>,
|
||||
~previewOffset as _: option<int>,
|
||||
) => (),
|
||||
setVolume: (_vol: float) => (),
|
||||
pause: () => (),
|
||||
togglePlayPause: () => (),
|
||||
setMuted: (muted: bool) => (),
|
||||
setMuted: (_muted: bool) => (),
|
||||
playNext: () => (),
|
||||
playPrevious: () => (),
|
||||
};
|
||||
let audioPlayerContext = React.createContext(value);
|
||||
}
|
||||
let audioPlayerContext = React.createContext(value)
|
||||
|
||||
let makeProps = (~value, ~children, ()) => {
|
||||
"value": value,
|
||||
"children": children,
|
||||
};
|
||||
let makeProps = (~value, ~children, ()) =>
|
||||
{
|
||||
"value": value,
|
||||
"children": children,
|
||||
}
|
||||
|
||||
let make = React.Context.provider(audioPlayerContext);
|
||||
};
|
||||
let make = React.Context.provider(audioPlayerContext)
|
||||
}
|
||||
|
||||
let useAudioPlayer = () => React.useContext(Provider.audioPlayerContext);
|
||||
let useAudioPlayer = () => React.useContext(Provider.audioPlayerContext)
|
||||
@@ -1,270 +0,0 @@
|
||||
open AudioPlayerProvider;
|
||||
|
||||
[@bs.val] external alert: string => unit = "alert";
|
||||
|
||||
let audio = Audio.make();
|
||||
|
||||
let _play = () => {
|
||||
Audio.play(audio);
|
||||
};
|
||||
|
||||
let _updateMetadata = (song: song) => {
|
||||
MediaMetadata.make({
|
||||
title: song.title,
|
||||
artist: song.artist,
|
||||
album: "Beatconnect",
|
||||
artwork: [|MediaMetadata.makeArtwork(song.id)|],
|
||||
})
|
||||
->MediaSession.setMediaSessionMetadata;
|
||||
};
|
||||
|
||||
let _setPreviewAudio = (beatmapSetId: int) => {
|
||||
Audio.setSrc(audio, {j|https://b.ppy.sh/preview/$beatmapSetId.mp3|j});
|
||||
};
|
||||
|
||||
let _setAudioSrc = (~audioFilePath, ~previewOffset=?, ()) => {
|
||||
Audio.setSrc(audio, audioFilePath);
|
||||
switch (previewOffset) {
|
||||
| Some(offset) => Audio.setCurrentTime(audio, offset)
|
||||
| None => ()
|
||||
};
|
||||
};
|
||||
|
||||
let pause = () => {
|
||||
Audio.pause(audio);
|
||||
};
|
||||
|
||||
let togglePlayPause = () => Audio.paused(audio) ? _play() : pause();
|
||||
|
||||
let setVolume = Audio.setVolume(audio);
|
||||
|
||||
[@react.component]
|
||||
let make = (~children) => {
|
||||
let playlistErrorCount = React.useRef(0);
|
||||
let (playingState, setPlayingState) = React.useState(() => initialState);
|
||||
let (playlist: playlist, setPlaylist) = React.useState(() => [||]);
|
||||
let (playlistID: string, setPlaylistID) = React.useState(() => "");
|
||||
|
||||
let _canPlay = (offset: int) =>
|
||||
if (playlist->Belt_Array.length > 0) {
|
||||
let currentSongIndex =
|
||||
playlist->Belt_Array.getIndexBy(item =>
|
||||
item.id == playingState.beatmapSetId
|
||||
);
|
||||
switch (currentSongIndex) {
|
||||
| None => None
|
||||
| Some(index) =>
|
||||
index + offset < playlist->Js_array.length && index + offset > (-1)
|
||||
? Some(index + offset) : None
|
||||
};
|
||||
} else {
|
||||
None;
|
||||
};
|
||||
|
||||
let _canPlayNextSong = () => _canPlay(1);
|
||||
let _canPlayPrevSong = () => _canPlay(-1);
|
||||
|
||||
let setPlaylist = (~beatmapPlaylist: playlist, ~playlistID=?, ()) => {
|
||||
setPlaylist(_ => beatmapPlaylist);
|
||||
switch (playlistID) {
|
||||
| Some(id) => setPlaylistID(_ => id)
|
||||
| None => ()
|
||||
};
|
||||
};
|
||||
|
||||
let _stop = () => {
|
||||
pause();
|
||||
setPlaylist(~beatmapPlaylist=[||], ~playlistID="", ());
|
||||
};
|
||||
|
||||
let playFromPlaylist = (playlistindex: int) => {
|
||||
let nextSong = playlist[playlistindex];
|
||||
Audio.setSrc(audio, nextSong.path);
|
||||
_updateMetadata({
|
||||
id: nextSong.id,
|
||||
title: nextSong.title,
|
||||
artist: nextSong.artist,
|
||||
});
|
||||
_play();
|
||||
setPlayingState(oldState =>
|
||||
{
|
||||
...oldState,
|
||||
isPlaying: false,
|
||||
beatmapSetId: nextSong.id,
|
||||
title: nextSong.title,
|
||||
artist: nextSong.artist,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
let playNext = () => {
|
||||
switch (_canPlayNextSong()) {
|
||||
| Some(nextSong) => playFromPlaylist(nextSong)
|
||||
| None => ()
|
||||
};
|
||||
};
|
||||
|
||||
let playPrevious = () => {
|
||||
switch (_canPlayPrevSong()) {
|
||||
| Some(prevSong) => playFromPlaylist(prevSong)
|
||||
| None => ()
|
||||
};
|
||||
};
|
||||
|
||||
React.useEffect3(
|
||||
() => {
|
||||
IPCRenderer.send(
|
||||
UPDATE_THUMB_BAR({
|
||||
isPlaying: playingState.isPlaying,
|
||||
canPlayNext: playingState.hasNext,
|
||||
canPlayPrev: playingState.hasPrev,
|
||||
}),
|
||||
);
|
||||
IPCRenderer.on("EXEC_PREV", playPrevious);
|
||||
IPCRenderer.on("EXEC_NEXT", playNext);
|
||||
Some(
|
||||
() => {
|
||||
IPCRenderer.removeListener("EXEC_PREV", playPrevious);
|
||||
IPCRenderer.removeListener("EXEC_NEXT", playNext);
|
||||
},
|
||||
);
|
||||
},
|
||||
(playingState.isPlaying, playingState.hasNext, playingState.hasPrev),
|
||||
);
|
||||
|
||||
React.useEffect0(() => {
|
||||
MediaSession.setActionHandler(`play, Some(_play));
|
||||
MediaSession.setActionHandler(`pause, Some(pause));
|
||||
MediaSession.setActionHandler(`stop, Some(_stop));
|
||||
IPCRenderer.on("EXEC_PLAY_PAUSE", togglePlayPause);
|
||||
None;
|
||||
});
|
||||
|
||||
let updateMediaHandlers = () => {
|
||||
let next =
|
||||
switch (_canPlayNextSong()) {
|
||||
| Some(nextSongindex) =>
|
||||
setPlayingState(prevState => {...prevState, hasNext: true});
|
||||
Some(() => playFromPlaylist(nextSongindex));
|
||||
| None =>
|
||||
setPlayingState(prevState => {...prevState, hasNext: false});
|
||||
None;
|
||||
};
|
||||
|
||||
MediaSession.setActionHandler(`nexttrack, next);
|
||||
|
||||
let previous =
|
||||
switch (_canPlayPrevSong()) {
|
||||
| Some(prevSongindex) =>
|
||||
setPlayingState(prevState => {...prevState, hasPrev: true});
|
||||
Some(() => playFromPlaylist(prevSongindex));
|
||||
| None =>
|
||||
setPlayingState(prevState => {...prevState, hasPrev: false});
|
||||
None;
|
||||
};
|
||||
|
||||
MediaSession.setActionHandler(`previoustrack, previous);
|
||||
};
|
||||
|
||||
React.useEffect2(
|
||||
() => {
|
||||
updateMediaHandlers();
|
||||
None;
|
||||
},
|
||||
(playingState.beatmapSetId, playlist),
|
||||
);
|
||||
|
||||
let setAudio =
|
||||
(
|
||||
~song: song,
|
||||
~audioFilePath: option(string),
|
||||
~previewOffset: option(int),
|
||||
) => {
|
||||
setPlaylist(~beatmapPlaylist=[||], ~playlistID="", ());
|
||||
_updateMetadata(song);
|
||||
|
||||
switch (audioFilePath, previewOffset) {
|
||||
| (None, None) => _setPreviewAudio(song.id)
|
||||
| (None, Some(_)) => _setPreviewAudio(song.id)
|
||||
| (Some(audioFilePath), None) => _setAudioSrc(~audioFilePath, ())
|
||||
| (Some(audioFilePath), Some(previewOffset)) =>
|
||||
_setAudioSrc(~audioFilePath, ~previewOffset, ())
|
||||
};
|
||||
|
||||
_play();
|
||||
setPlayingState(oldState =>
|
||||
{
|
||||
...oldState,
|
||||
isPlaying: false,
|
||||
beatmapSetId: song.id,
|
||||
artist: song.artist,
|
||||
title: song.title,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
let setMuted = muted => {
|
||||
Audio.setMuted(audio, muted);
|
||||
setPlayingState(oldState => {...oldState, muted});
|
||||
};
|
||||
|
||||
Audio.onended(audio, _e => {
|
||||
switch (_canPlayNextSong()) {
|
||||
| Some(nextSongindex) => playFromPlaylist(nextSongindex)
|
||||
| None => DiscordRPC.clearActivity()
|
||||
}
|
||||
});
|
||||
|
||||
Audio.onpause(
|
||||
audio,
|
||||
_e => {
|
||||
Js.log("PAUSEEEE");
|
||||
setPlayingState(oldState => {...oldState, isPlaying: false});
|
||||
},
|
||||
);
|
||||
|
||||
Audio.onplay(audio, _e => {
|
||||
setPlayingState(oldState => {...oldState, isPlaying: true})
|
||||
});
|
||||
|
||||
Audio.oncanplay(audio, _e =>
|
||||
setPlayingState(oldState => {...oldState, isPlaying: true})
|
||||
);
|
||||
|
||||
Audio.onvolumechange(audio, e => {
|
||||
setPlayingState(oldState => {...oldState, volume: e.target.volume})
|
||||
});
|
||||
|
||||
Audio.onerror(
|
||||
audio,
|
||||
_e => {
|
||||
setPlayingState(oldState => {...oldState, isPlaying: false});
|
||||
let skipCount = playlistErrorCount->React.Ref.current;
|
||||
if (skipCount > 12 || skipCount >= playlist->Js_array.length - 1) {
|
||||
playlistErrorCount->React.Ref.setCurrent(0);
|
||||
setPlaylist(~beatmapPlaylist=[||], ~playlistID="", ());
|
||||
alert(
|
||||
"Failed to play a song one or multiple times, please check your osu songs folder setting in the Settings section",
|
||||
);
|
||||
} else {
|
||||
playNext();
|
||||
playlistErrorCount->React.Ref.setCurrent(skipCount + 1);
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
let value = {
|
||||
playingState,
|
||||
pause,
|
||||
setAudio,
|
||||
setPlaylist,
|
||||
setVolume,
|
||||
togglePlayPause,
|
||||
setMuted,
|
||||
playlist,
|
||||
playNext,
|
||||
playPrevious,
|
||||
playlistID,
|
||||
};
|
||||
<Provider value> children </Provider>;
|
||||
};
|
||||
@@ -0,0 +1,232 @@
|
||||
open AudioPlayerProvider
|
||||
|
||||
@val external alert: string => unit = "alert"
|
||||
|
||||
let audio = Audio.make()
|
||||
|
||||
let _play = () => Audio.play(audio)
|
||||
|
||||
let _updateMetadata = (song: song) =>
|
||||
MediaMetadata.make({
|
||||
title: song.title,
|
||||
artist: song.artist,
|
||||
album: "Beatconnect",
|
||||
artwork: [MediaMetadata.makeArtwork(song.id->Js.Int.toString)],
|
||||
})->MediaSession.setMediaSessionMetadata
|
||||
|
||||
let _setPreviewAudio = (beatmapSetId: int) =>
|
||||
Audio.setSrc(audio, `https://b.ppy.sh/preview/${beatmapSetId->Js.Int.toString}.mp3`)
|
||||
|
||||
let _setAudioSrc = (~audioFilePath, ~previewOffset=?, ()) => {
|
||||
Audio.setSrc(audio, audioFilePath)
|
||||
switch previewOffset {
|
||||
| Some(offset) => Audio.setCurrentTime(audio, offset)
|
||||
| None => ()
|
||||
}
|
||||
}
|
||||
|
||||
let pause = () => Audio.pause(audio)
|
||||
|
||||
let togglePlayPause = () => Audio.paused(audio) ? _play() : pause()
|
||||
|
||||
let setVolume = Audio.setVolume(audio)
|
||||
|
||||
@react.component
|
||||
let make = (~children) => {
|
||||
let playlistErrorCount = React.useRef(0)
|
||||
let (playingState, setPlayingState) = React.useState(() => initialState)
|
||||
let (playlist: playlist, setPlaylist) = React.useState(() => [])
|
||||
let (playlistID: string, setPlaylistID) = React.useState(() => "")
|
||||
|
||||
let _canPlay = (offset: int) =>
|
||||
if playlist->Belt_Array.length > 0 {
|
||||
let currentSongIndex =
|
||||
playlist->Belt_Array.getIndexBy(item => item.id == playingState.beatmapSetId)
|
||||
switch currentSongIndex {
|
||||
| None => None
|
||||
| Some(index) =>
|
||||
index + offset < playlist->Js_array.length && index + offset > -1
|
||||
? Some(index + offset)
|
||||
: None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
let _canPlayNextSong = () => _canPlay(1)
|
||||
let _canPlayPrevSong = () => _canPlay(-1)
|
||||
|
||||
let setPlaylist = (~beatmapPlaylist: playlist, ~playlistID=?, ()) => {
|
||||
setPlaylist(_ => beatmapPlaylist)
|
||||
switch playlistID {
|
||||
| Some(id) => setPlaylistID(_ => id)
|
||||
| None => ()
|
||||
}
|
||||
}
|
||||
|
||||
let _stop = () => {
|
||||
pause()
|
||||
setPlaylist(~beatmapPlaylist=[], ~playlistID="", ())
|
||||
}
|
||||
|
||||
let playFromPlaylist = (playlistindex: int) => {
|
||||
let nextSong = playlist[playlistindex]
|
||||
Audio.setSrc(audio, nextSong.path)
|
||||
_updateMetadata({
|
||||
id: nextSong.id,
|
||||
title: nextSong.title,
|
||||
artist: nextSong.artist,
|
||||
})
|
||||
_play()
|
||||
setPlayingState(oldState => {
|
||||
...oldState,
|
||||
isPlaying: false,
|
||||
beatmapSetId: nextSong.id,
|
||||
title: nextSong.title,
|
||||
artist: nextSong.artist,
|
||||
})
|
||||
}
|
||||
|
||||
let playNext = () =>
|
||||
switch _canPlayNextSong() {
|
||||
| Some(nextSong) => playFromPlaylist(nextSong)
|
||||
| None => ()
|
||||
}
|
||||
|
||||
let playPrevious = () =>
|
||||
switch _canPlayPrevSong() {
|
||||
| Some(prevSong) => playFromPlaylist(prevSong)
|
||||
| None => ()
|
||||
}
|
||||
|
||||
React.useEffect3(() => {
|
||||
IPCRenderer.send(
|
||||
UPDATE_THUMB_BAR({
|
||||
isPlaying: playingState.isPlaying,
|
||||
canPlayNext: playingState.hasNext,
|
||||
canPlayPrev: playingState.hasPrev,
|
||||
}),
|
||||
)
|
||||
IPCRenderer.on("EXEC_PREV", playPrevious)
|
||||
IPCRenderer.on("EXEC_NEXT", playNext)
|
||||
Some(
|
||||
() => {
|
||||
IPCRenderer.removeListener("EXEC_PREV", playPrevious)
|
||||
IPCRenderer.removeListener("EXEC_NEXT", playNext)
|
||||
},
|
||||
)
|
||||
}, (playingState.isPlaying, playingState.hasNext, playingState.hasPrev))
|
||||
|
||||
React.useEffect0(() => {
|
||||
MediaSession.setActionHandler(#play, Some(_play))
|
||||
MediaSession.setActionHandler(#pause, Some(pause))
|
||||
MediaSession.setActionHandler(#stop, Some(_stop))
|
||||
IPCRenderer.on("EXEC_PLAY_PAUSE", togglePlayPause)
|
||||
None
|
||||
})
|
||||
|
||||
let updateMediaHandlers = () => {
|
||||
let next = switch _canPlayNextSong() {
|
||||
| Some(nextSongindex) =>
|
||||
setPlayingState(prevState => {...prevState, hasNext: true})
|
||||
Some(() => playFromPlaylist(nextSongindex))
|
||||
| None =>
|
||||
setPlayingState(prevState => {...prevState, hasNext: false})
|
||||
None
|
||||
}
|
||||
|
||||
MediaSession.setActionHandler(#nexttrack, next)
|
||||
|
||||
let previous = switch _canPlayPrevSong() {
|
||||
| Some(prevSongindex) =>
|
||||
setPlayingState(prevState => {...prevState, hasPrev: true})
|
||||
Some(() => playFromPlaylist(prevSongindex))
|
||||
| None =>
|
||||
setPlayingState(prevState => {...prevState, hasPrev: false})
|
||||
None
|
||||
}
|
||||
|
||||
MediaSession.setActionHandler(#previoustrack, previous)
|
||||
}
|
||||
|
||||
React.useEffect2(() => {
|
||||
updateMediaHandlers()
|
||||
None
|
||||
}, (playingState.beatmapSetId, playlist))
|
||||
|
||||
let setAudio = (~song: song, ~audioFilePath: option<string>, ~previewOffset: option<int>) => {
|
||||
setPlaylist(~beatmapPlaylist=[], ~playlistID="", ())
|
||||
_updateMetadata(song)
|
||||
|
||||
switch (audioFilePath, previewOffset) {
|
||||
| (None, None) => _setPreviewAudio(song.id)
|
||||
| (None, Some(_)) => _setPreviewAudio(song.id)
|
||||
| (Some(audioFilePath), None) => _setAudioSrc(~audioFilePath, ())
|
||||
| (Some(audioFilePath), Some(previewOffset)) => _setAudioSrc(~audioFilePath, ~previewOffset, ())
|
||||
}
|
||||
|
||||
_play()
|
||||
setPlayingState(oldState => {
|
||||
...oldState,
|
||||
isPlaying: false,
|
||||
beatmapSetId: song.id,
|
||||
artist: song.artist,
|
||||
title: song.title,
|
||||
})
|
||||
}
|
||||
|
||||
let setMuted = muted => {
|
||||
Audio.setMuted(audio, muted)
|
||||
setPlayingState(oldState => {...oldState, muted: muted})
|
||||
}
|
||||
|
||||
Audio.onended(audio, _e =>
|
||||
switch _canPlayNextSong() {
|
||||
| Some(nextSongindex) => playFromPlaylist(nextSongindex)
|
||||
| None => DiscordRPC.clearActivity()
|
||||
}
|
||||
)
|
||||
|
||||
Audio.onpause(audio, _e => {
|
||||
Js.log("PAUSEEEE")
|
||||
setPlayingState(oldState => {...oldState, isPlaying: false})
|
||||
})
|
||||
|
||||
Audio.onplay(audio, _e => setPlayingState(oldState => {...oldState, isPlaying: true}))
|
||||
|
||||
Audio.oncanplay(audio, _e => setPlayingState(oldState => {...oldState, isPlaying: true}))
|
||||
|
||||
Audio.onvolumechange(audio, e =>
|
||||
setPlayingState(oldState => {...oldState, volume: e.target.volume})
|
||||
)
|
||||
|
||||
Audio.onerror(audio, _e => {
|
||||
setPlayingState(oldState => {...oldState, isPlaying: false})
|
||||
let skipCount = playlistErrorCount.current
|
||||
if skipCount > 12 || skipCount >= playlist->Js_array.length - 1 {
|
||||
playlistErrorCount.current = 0
|
||||
setPlaylist(~beatmapPlaylist=[], ~playlistID="", ())
|
||||
alert(
|
||||
"Failed to play a song one or multiple times, please check your osu songs folder setting in the Settings section",
|
||||
)
|
||||
} else {
|
||||
playNext()
|
||||
playlistErrorCount.current = skipCount + 1
|
||||
}
|
||||
})
|
||||
|
||||
let value = {
|
||||
playingState: playingState,
|
||||
pause: pause,
|
||||
setAudio: setAudio,
|
||||
setPlaylist: setPlaylist,
|
||||
setVolume: setVolume,
|
||||
togglePlayPause: togglePlayPause,
|
||||
setMuted: setMuted,
|
||||
playlist: playlist,
|
||||
playNext: playNext,
|
||||
playPrevious: playPrevious,
|
||||
playlistID: playlistID,
|
||||
}
|
||||
<Provider value> children </Provider>
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
[@bs.deriving {jsConverter: newType}]
|
||||
type status = [ | `running | `terminated | `error];
|
||||
|
||||
module Task = {
|
||||
type t = {
|
||||
name: string,
|
||||
description: string,
|
||||
status,
|
||||
section: Sections.t,
|
||||
};
|
||||
|
||||
module Setters = {
|
||||
let setName = (name, t) => {...t, name};
|
||||
let setDescription = (description, t) => {...t, description};
|
||||
let setStatus = (status, t) => {...t, status};
|
||||
let setSection = (section, t) => {...t, section};
|
||||
};
|
||||
};
|
||||
|
||||
type partialTask = {
|
||||
name: string,
|
||||
description: option(string),
|
||||
status: option(status),
|
||||
};
|
||||
|
||||
type value = {
|
||||
add: Task.t => unit,
|
||||
update: partialTask => unit,
|
||||
terminate: string => unit,
|
||||
tasks: Js.Array.t(Task.t),
|
||||
};
|
||||
|
||||
module Provider = {
|
||||
let value = {
|
||||
add: task => Js.log(task),
|
||||
update: partialTask => Js.log(partialTask),
|
||||
terminate: taskName => Js.log(taskName),
|
||||
tasks: [||],
|
||||
};
|
||||
let taskContext = React.createContext(value);
|
||||
|
||||
let makeProps = (~value, ~children, ()) => {
|
||||
"value": value,
|
||||
"children": children,
|
||||
};
|
||||
|
||||
let make = React.Context.provider(taskContext);
|
||||
|
||||
let updateTaskAt = (index, tasks, task) =>
|
||||
tasks->Belt.Array.mapWithIndex((i, currentTask) =>
|
||||
i === index ? task : currentTask
|
||||
);
|
||||
};
|
||||
|
||||
let useTasks = () => React.useContext(Provider.taskContext);
|
||||
|
||||
[@react.component]
|
||||
let make = (~children) => {
|
||||
let (tasks, setTasks) = React.useState(() => [||]);
|
||||
let tasksRef = React.useRef(tasks);
|
||||
React.useEffect1(
|
||||
() => {
|
||||
React.Ref.setCurrent(tasksRef, tasks);
|
||||
None;
|
||||
},
|
||||
[|tasks|],
|
||||
);
|
||||
let add = (task: Task.t) =>
|
||||
setTasks(oldTasks => Js.Array.concat([|task|], oldTasks));
|
||||
let update = (partialTask: partialTask) => {
|
||||
let tasks = React.Ref.current(tasksRef);
|
||||
let taskIndex =
|
||||
Js.Array.findIndex(
|
||||
(task: Task.t) => task.name == partialTask.name,
|
||||
tasks,
|
||||
);
|
||||
if (taskIndex != (-1)) {
|
||||
let {description, status} = partialTask;
|
||||
switch (description, status) {
|
||||
| (Some(description), Some(status)) =>
|
||||
setTasks(tasks =>
|
||||
tasks[taskIndex]
|
||||
|> Task.Setters.setDescription(description)
|
||||
|> Task.Setters.setStatus(status)
|
||||
|> Provider.updateTaskAt(taskIndex, tasks)
|
||||
)
|
||||
| (Some(description), None) =>
|
||||
setTasks(tasks =>
|
||||
tasks[taskIndex]
|
||||
|> Task.Setters.setDescription(description)
|
||||
|> Provider.updateTaskAt(taskIndex, tasks)
|
||||
)
|
||||
| (None, Some(status)) =>
|
||||
setTasks(tasks =>
|
||||
tasks[taskIndex]
|
||||
|> Task.Setters.setStatus(status)
|
||||
|> Provider.updateTaskAt(taskIndex, tasks)
|
||||
)
|
||||
| (None, None) => ()
|
||||
};
|
||||
};
|
||||
};
|
||||
let terminate = (taskName: string) =>
|
||||
setTasks(oldTasks =>
|
||||
Js.Array.filter((task: Task.t) => !(task.name == taskName), oldTasks)
|
||||
);
|
||||
let value = {add, terminate, update, tasks};
|
||||
<Provider value> children </Provider>;
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
@deriving({jsConverter: newType})
|
||||
type status = [#running | #terminated | #error]
|
||||
|
||||
module Task = {
|
||||
type t = {
|
||||
name: string,
|
||||
description: string,
|
||||
status: status,
|
||||
section: Sections.t,
|
||||
}
|
||||
|
||||
module Setters = {
|
||||
let setName = (t, name) => {...t, name: name}
|
||||
let setDescription = (t, description) => {...t, description: description}
|
||||
let setStatus = (t, status) => {...t, status: status}
|
||||
let setSection = (t, section) => {...t, section: section}
|
||||
}
|
||||
}
|
||||
|
||||
type partialTask = {
|
||||
name: string,
|
||||
description: option<string>,
|
||||
status: option<status>,
|
||||
}
|
||||
|
||||
type value = {
|
||||
add: Task.t => unit,
|
||||
update: partialTask => unit,
|
||||
terminate: string => unit,
|
||||
tasks: Js.Array.t<Task.t>,
|
||||
}
|
||||
|
||||
module Provider = {
|
||||
let value = {
|
||||
add: task => Js.log(task),
|
||||
update: partialTask => Js.log(partialTask),
|
||||
terminate: taskName => Js.log(taskName),
|
||||
tasks: [],
|
||||
}
|
||||
let taskContext = React.createContext(value)
|
||||
|
||||
let makeProps = (~value, ~children, ()) =>
|
||||
{
|
||||
"value": value,
|
||||
"children": children,
|
||||
}
|
||||
|
||||
let make = React.Context.provider(taskContext)
|
||||
|
||||
let updateTaskAt = (task, index, tasks) =>
|
||||
tasks->Belt.Array.mapWithIndex((i, currentTask) => i === index ? task : currentTask)
|
||||
}
|
||||
|
||||
let useTasks = () => React.useContext(Provider.taskContext)
|
||||
|
||||
@react.component
|
||||
let make = (~children) => {
|
||||
let (tasks, setTasks) = React.useState(() => [])
|
||||
let tasksRef = React.useRef(tasks)
|
||||
React.useEffect1(() => {
|
||||
tasksRef.current = tasks
|
||||
None
|
||||
}, [tasks])
|
||||
let add = (task: Task.t) => setTasks(oldTasks => Js.Array.concat([task], oldTasks))
|
||||
let update = (partialTask: partialTask) => {
|
||||
let tasks = tasksRef.current
|
||||
let taskIndex = Js.Array.findIndex((task: Task.t) => task.name == partialTask.name, tasks)
|
||||
if taskIndex != -1 {
|
||||
let {description, status} = partialTask
|
||||
switch (description, status) {
|
||||
| (Some(description), Some(status)) =>
|
||||
setTasks(tasks =>
|
||||
tasks[taskIndex]
|
||||
->Task.Setters.setDescription(description)
|
||||
->Task.Setters.setStatus(status)
|
||||
->Provider.updateTaskAt(taskIndex, tasks)
|
||||
)
|
||||
| (Some(description), None) =>
|
||||
setTasks(tasks =>
|
||||
tasks[taskIndex]
|
||||
->Task.Setters.setDescription(description)
|
||||
->Provider.updateTaskAt(taskIndex, tasks)
|
||||
)
|
||||
| (None, Some(status)) =>
|
||||
setTasks(tasks =>
|
||||
tasks[taskIndex]->Task.Setters.setStatus(status)->Provider.updateTaskAt(taskIndex, tasks)
|
||||
)
|
||||
| (None, None) => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
let terminate = (taskName: string) =>
|
||||
setTasks(oldTasks => Js.Array.filter((task: Task.t) => !(task.name == taskName), oldTasks))
|
||||
let value = {add: add, terminate: terminate, update: update, tasks: tasks}
|
||||
<Provider value> children </Provider>
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
[@bs.module "./discordRPC.js"]
|
||||
external setPlayingSongPresence: (string, string) => unit =
|
||||
"setPlayingSongPresence";
|
||||
[@bs.module "./discordRPC.js"]
|
||||
external clearActivity: unit => unit = "clearActivity";
|
||||
@@ -0,0 +1,4 @@
|
||||
@module("./discordRPC.js")
|
||||
external setPlayingSongPresence: (string, string) => unit = "setPlayingSongPresence"
|
||||
@module("./discordRPC.js")
|
||||
external clearActivity: unit => unit = "clearActivity"
|
||||
@@ -1,29 +0,0 @@
|
||||
[@bs.deriving jsConverter]
|
||||
type jsRenderIconsArgs = {
|
||||
name: string,
|
||||
color: option(string),
|
||||
width: option(int),
|
||||
height: option(int),
|
||||
};
|
||||
|
||||
[@bs.module "./renderIcons"]
|
||||
external jsRenderIcons:
|
||||
{
|
||||
.
|
||||
"color": option(string),
|
||||
"height": option(int),
|
||||
"name": string,
|
||||
"width": option(int),
|
||||
} =>
|
||||
React.element =
|
||||
"default";
|
||||
|
||||
let make =
|
||||
(
|
||||
~name: string,
|
||||
~color: option(string)=?,
|
||||
~width: option(int)=?,
|
||||
~height: option(int)=?,
|
||||
(),
|
||||
) =>
|
||||
{name, color, width, height}->jsRenderIconsArgsToJs->jsRenderIcons;
|
||||
@@ -0,0 +1,23 @@
|
||||
@deriving(jsConverter)
|
||||
type jsRenderIconsArgs = {
|
||||
name: string,
|
||||
color: option<string>,
|
||||
width: option<int>,
|
||||
height: option<int>,
|
||||
}
|
||||
|
||||
@module("./renderIcons")
|
||||
external jsRenderIcons: {
|
||||
"color": option<string>,
|
||||
"height": option<int>,
|
||||
"name": string,
|
||||
"width": option<int>,
|
||||
} => React.element = "default"
|
||||
|
||||
let make = (
|
||||
~name: string,
|
||||
~color: option<string>=?,
|
||||
~width: option<int>=?,
|
||||
~height: option<int>=?,
|
||||
(),
|
||||
) => {name: name, color: color, width: width, height: height}->jsRenderIconsArgsToJs->jsRenderIcons
|
||||
@@ -1,2 +0,0 @@
|
||||
[@bs.deriving {jsConverter: newType}]
|
||||
type t = [ | `Beatmaps | `Packs | `Downloads | `Bot | `Settings];
|
||||
@@ -0,0 +1,2 @@
|
||||
@deriving({jsConverter: newType})
|
||||
type t = [#Beatmaps | #Packs | #Downloads | #Bot | #Settings]
|
||||
@@ -1,138 +0,0 @@
|
||||
open Css;
|
||||
|
||||
let makeBaseStyle = () =>
|
||||
style([
|
||||
border(px(2), solid, hex("2c3e50")),
|
||||
borderRadius(rem(0.25)),
|
||||
fontSize(rem(0.8)),
|
||||
padding3(~top=rem(0.1), ~h=rem(0.45), ~bottom=rem(0.2)),
|
||||
display(inlineFlex),
|
||||
alignItems(center),
|
||||
whiteSpace(nowrap),
|
||||
]);
|
||||
|
||||
let makeStatusStyle = (status, difficulty) =>
|
||||
switch (status) {
|
||||
| "info" => style([backgroundColor(hex("3498db"))])
|
||||
| "pending" =>
|
||||
style([
|
||||
backgroundColor(
|
||||
difficulty->Belt.Option.mapWithDefault(
|
||||
rgba(241, 196, 15),
|
||||
PpyHelpers.getBeatmapDifficultyColorRGBA,
|
||||
0.5,
|
||||
),
|
||||
),
|
||||
borderColor(
|
||||
difficulty->Belt.Option.mapWithDefault(
|
||||
rgba(241, 196, 15),
|
||||
PpyHelpers.getBeatmapDifficultyColorRGBA,
|
||||
0.8,
|
||||
),
|
||||
),
|
||||
hover([
|
||||
backgroundColor(rgba(241, 196, 15, 0.7)),
|
||||
borderColor(rgb(241, 196, 15)),
|
||||
]),
|
||||
])
|
||||
| "qualified" =>
|
||||
style([
|
||||
backgroundColor(rgba(241, 196, 15, 0.50)),
|
||||
borderColor(rgba(241, 196, 15, 0.8)),
|
||||
hover([
|
||||
backgroundColor(rgba(241, 196, 15, 0.7)),
|
||||
borderColor(rgb(241, 196, 15)),
|
||||
]),
|
||||
])
|
||||
| "graveyard" =>
|
||||
style([
|
||||
backgroundColor(rgba(231, 76, 60, 0.50)),
|
||||
borderColor(rgba(231, 76, 60, 0.8)),
|
||||
hover([
|
||||
backgroundColor(rgba(231, 76, 60, 0.7)),
|
||||
borderColor(rgb(231, 76, 60)),
|
||||
]),
|
||||
])
|
||||
| "WIP" =>
|
||||
style([
|
||||
backgroundColor(rgba(231, 76, 60, 0.50)),
|
||||
borderColor(rgba(231, 76, 60, 0.8)),
|
||||
hover([
|
||||
backgroundColor(rgba(231, 76, 60, 0.7)),
|
||||
borderColor(rgb(231, 76, 60)),
|
||||
]),
|
||||
])
|
||||
| "loved" =>
|
||||
style([
|
||||
backgroundColor(rgba(222, 90, 148, 0.50)),
|
||||
borderColor(rgba(222, 90, 148, 0.8)),
|
||||
hover([
|
||||
backgroundColor(rgba(222, 90, 148, 0.7)),
|
||||
borderColor(rgb(222, 90, 148)),
|
||||
]),
|
||||
])
|
||||
| "ranked" =>
|
||||
style([
|
||||
backgroundColor(
|
||||
difficulty->Belt.Option.mapWithDefault(
|
||||
rgba(46, 204, 113),
|
||||
PpyHelpers.getBeatmapDifficultyColorRGBA,
|
||||
0.5,
|
||||
),
|
||||
),
|
||||
borderColor(
|
||||
difficulty->Belt.Option.mapWithDefault(
|
||||
rgba(46, 204, 113),
|
||||
PpyHelpers.getBeatmapDifficultyColorRGBA,
|
||||
0.8,
|
||||
),
|
||||
),
|
||||
hover([
|
||||
backgroundColor(rgba(46, 204, 113, 0.7)),
|
||||
borderColor(rgb(46, 204, 113)),
|
||||
]),
|
||||
])
|
||||
| _ => style([backgroundColor(hex("2c3e50"))])
|
||||
};
|
||||
|
||||
let makeStyle = (status, difficulty) =>
|
||||
[makeBaseStyle(), makeStatusStyle(status, difficulty)]->merge;
|
||||
|
||||
[@react.component]
|
||||
let make =
|
||||
(
|
||||
~status,
|
||||
~difficulty: option(float),
|
||||
~difficultyText: option(string),
|
||||
~style=?,
|
||||
) => {
|
||||
let (text, setText) = React.useState(() => status);
|
||||
|
||||
React.useEffect1(
|
||||
() => {
|
||||
setText(_ =>
|
||||
switch (difficultyText) {
|
||||
| Some(difficultyText) => difficultyText
|
||||
| None => status
|
||||
}
|
||||
);
|
||||
None;
|
||||
},
|
||||
[|difficultyText|],
|
||||
);
|
||||
|
||||
<span
|
||||
className={makeStyle(status, difficulty)}
|
||||
?style
|
||||
onMouseEnter={_ => setText(_ => status)}
|
||||
onMouseLeave={_ =>
|
||||
setText(_ =>
|
||||
switch (difficultyText) {
|
||||
| Some(difficultyText) => difficultyText
|
||||
| None => status
|
||||
}
|
||||
)
|
||||
}>
|
||||
<span> text->React.string </span>
|
||||
</span>;
|
||||
};
|
||||
@@ -0,0 +1,110 @@
|
||||
open CssJs
|
||||
|
||||
let makeBaseStyle = () =>
|
||||
style(. [
|
||||
border(px(2), solid, hex("2c3e50")),
|
||||
borderRadius(rem(0.25)),
|
||||
fontSize(rem(0.8)),
|
||||
padding3(~top=rem(0.1), ~h=rem(0.45), ~bottom=rem(0.2)),
|
||||
display(inlineFlex),
|
||||
alignItems(center),
|
||||
whiteSpace(nowrap),
|
||||
])
|
||||
|
||||
let makeStatusStyle = (status, difficulty) =>
|
||||
switch status {
|
||||
| "info" => style(. [backgroundColor(hex("3498db"))])
|
||||
| "pending" =>
|
||||
style(. [
|
||||
backgroundColor(
|
||||
difficulty->Belt.Option.mapWithDefault(
|
||||
rgba(241, 196, 15),
|
||||
PpyHelpers.getBeatmapDifficultyColorRGBA,
|
||||
#num(0.5),
|
||||
),
|
||||
),
|
||||
borderColor(
|
||||
difficulty->Belt.Option.mapWithDefault(
|
||||
rgba(241, 196, 15),
|
||||
PpyHelpers.getBeatmapDifficultyColorRGBA,
|
||||
#num(0.8),
|
||||
),
|
||||
),
|
||||
hover([backgroundColor(rgba(241, 196, 15, #num(0.7))), borderColor(rgb(241, 196, 15))]),
|
||||
])
|
||||
| "qualified" =>
|
||||
style(. [
|
||||
backgroundColor(rgba(241, 196, 15, #num(0.50))),
|
||||
borderColor(rgba(241, 196, 15, #num(0.8))),
|
||||
hover([backgroundColor(rgba(241, 196, 15, #num(0.7))), borderColor(rgb(241, 196, 15))]),
|
||||
])
|
||||
| "graveyard" =>
|
||||
style(. [
|
||||
backgroundColor(rgba(231, 76, 60, #num(0.50))),
|
||||
borderColor(rgba(231, 76, 60, #num(0.8))),
|
||||
hover([backgroundColor(rgba(231, 76, 60, #num(0.7))), borderColor(rgb(231, 76, 60))]),
|
||||
])
|
||||
| "WIP" =>
|
||||
style(. [
|
||||
backgroundColor(rgba(231, 76, 60, #num(0.50))),
|
||||
borderColor(rgba(231, 76, 60, #num(0.8))),
|
||||
hover([backgroundColor(rgba(231, 76, 60, #num(0.7))), borderColor(rgb(231, 76, 60))]),
|
||||
])
|
||||
| "loved" =>
|
||||
style(. [
|
||||
backgroundColor(rgba(222, 90, 148, #num(0.50))),
|
||||
borderColor(rgba(222, 90, 148, #num(0.8))),
|
||||
hover([backgroundColor(rgba(222, 90, 148, #num(0.7))), borderColor(rgb(222, 90, 148))]),
|
||||
])
|
||||
| "ranked" =>
|
||||
style(. [
|
||||
backgroundColor(
|
||||
difficulty->Belt.Option.mapWithDefault(
|
||||
rgba(46, 204, 113),
|
||||
PpyHelpers.getBeatmapDifficultyColorRGBA,
|
||||
#num(0.5),
|
||||
),
|
||||
),
|
||||
borderColor(
|
||||
difficulty->Belt.Option.mapWithDefault(
|
||||
rgba(46, 204, 113),
|
||||
PpyHelpers.getBeatmapDifficultyColorRGBA,
|
||||
#num(0.8),
|
||||
),
|
||||
),
|
||||
hover([backgroundColor(rgba(46, 204, 113, #num(0.7))), borderColor(rgb(46, 204, 113))]),
|
||||
])
|
||||
| _ => style(. [backgroundColor(hex("2c3e50"))])
|
||||
}
|
||||
|
||||
let makeStyle = (status, difficulty) =>
|
||||
[makeBaseStyle(), makeStatusStyle(status, difficulty)]->merge(. _)
|
||||
|
||||
@react.component
|
||||
let make = (~status, ~difficulty: option<float>, ~difficultyText: option<string>, ~style=?) => {
|
||||
let (text, setText) = React.useState(() => status)
|
||||
|
||||
React.useEffect1(() => {
|
||||
setText(_ =>
|
||||
switch difficultyText {
|
||||
| Some(difficultyText) => difficultyText
|
||||
| None => status
|
||||
}
|
||||
)
|
||||
None
|
||||
}, [difficultyText])
|
||||
|
||||
<span
|
||||
className={makeStyle(status, difficulty)}
|
||||
?style
|
||||
onMouseEnter={_ => setText(_ => status)}
|
||||
onMouseLeave={_ =>
|
||||
setText(_ =>
|
||||
switch difficultyText {
|
||||
| Some(difficultyText) => difficultyText
|
||||
| None => status
|
||||
}
|
||||
)}>
|
||||
<span> {text->React.string} </span>
|
||||
</span>
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
open Css;
|
||||
|
||||
let checkBoxStyle = (~color, ~activeColor) =>
|
||||
style([
|
||||
unsafe("-webkit-appearance", "none"),
|
||||
margin2(~v=auto, ~h=rem(1.)),
|
||||
width(px(20)),
|
||||
height(px(20)),
|
||||
border(px(1), solid, hex(color)),
|
||||
borderRadius(px(2)),
|
||||
verticalAlign(middle),
|
||||
backgroundColor(transparent),
|
||||
selector(
|
||||
"&:checked",
|
||||
[borderColor(hex(activeColor)), backgroundColor(hex(activeColor))],
|
||||
),
|
||||
]);
|
||||
|
||||
[@react.component]
|
||||
let make = (~checked, ~disabled, ~color, ~activeColor) => {
|
||||
<input
|
||||
className={checkBoxStyle(~color, ~activeColor)}
|
||||
type_="checkbox"
|
||||
checked
|
||||
disabled
|
||||
/>;
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
open CssJs
|
||||
|
||||
let checkBoxStyle = (~color, ~activeColor) =>
|
||||
style(. [
|
||||
unsafe("-webkit-appearance", "none"),
|
||||
margin2(~v=auto, ~h=rem(1.)),
|
||||
width(px(20)),
|
||||
height(px(20)),
|
||||
border(px(1), solid, hex(color)),
|
||||
borderRadius(px(2)),
|
||||
verticalAlign(middle),
|
||||
backgroundColor(transparent),
|
||||
selector(. "&:checked", [borderColor(hex(activeColor)), backgroundColor(hex(activeColor))]),
|
||||
])
|
||||
|
||||
@react.component
|
||||
let make = (~checked, ~disabled, ~color, ~activeColor) =>
|
||||
<input className={checkBoxStyle(~color, ~activeColor)} type_="checkbox" checked disabled />
|
||||
@@ -1,33 +1,32 @@
|
||||
open Css;
|
||||
open CssJs
|
||||
|
||||
let makeStyle = strokeDashoffset =>
|
||||
style([
|
||||
style(. [
|
||||
transition(~duration=350, "stroke-dashoffset"),
|
||||
transform(rotate(deg(-90.))),
|
||||
transformOrigin(pct(50.), pct(50.)),
|
||||
unsafe("stroke-dashoffset", strokeDashoffset),
|
||||
]);
|
||||
])
|
||||
|
||||
let floatToString = Js.Float.toString;
|
||||
let floatToString = Js.Float.toString
|
||||
|
||||
[@react.component]
|
||||
@react.component
|
||||
let make = (~radius, ~stroke, ~progress) => {
|
||||
let normalizedRadius = radius -. stroke *. 2.;
|
||||
let circumference = normalizedRadius *. 2. *. Js.Math._PI;
|
||||
let strokeDashoffset =
|
||||
(circumference -. progress /. 100. *. circumference)->floatToString;
|
||||
let size = (radius *. 2.)->floatToString;
|
||||
let normalizedRadius = radius -. stroke *. 2.
|
||||
let circumference = normalizedRadius *. 2. *. Js.Math._PI
|
||||
let strokeDashoffset = (circumference -. progress /. 100. *. circumference)->floatToString
|
||||
let size = (radius *. 2.)->floatToString
|
||||
|
||||
<svg height=size width=size style={ReactDOMRe.Style.make(~margin="0", ())}>
|
||||
<svg height=size width=size style={ReactDOMStyle.make(~margin="0", ())}>
|
||||
<circle
|
||||
className={makeStyle(strokeDashoffset)}
|
||||
stroke="white"
|
||||
fill="transparent"
|
||||
strokeWidth={stroke->floatToString}
|
||||
strokeDasharray={j|$circumference $circumference|j}
|
||||
strokeDasharray={`${circumference->Js.Float.toString} ${circumference->Js.Float.toString}`}
|
||||
r={normalizedRadius->floatToString}
|
||||
cx={radius->floatToString}
|
||||
cy={radius->floatToString}
|
||||
/>
|
||||
</svg>;
|
||||
};
|
||||
</svg>
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
open Css;
|
||||
let makeWrapperStyle = () =>
|
||||
style([
|
||||
zIndex(500),
|
||||
position(fixed),
|
||||
right(zero),
|
||||
display(`flex),
|
||||
alignItems(center),
|
||||
]);
|
||||
|
||||
let makeControlStyle = (~bgColor=?, ~spacer=false, ()) =>
|
||||
style([
|
||||
unsafe("WebkitAppRegion", "no-drag"),
|
||||
padding2(~v=zero, ~h=px(7)),
|
||||
selector(
|
||||
"&:hover",
|
||||
[
|
||||
backgroundColor(
|
||||
switch (bgColor) {
|
||||
| None => rgba(255, 255, 255, 0.25)
|
||||
| Some(c) => c
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
marginLeft(spacer ? `auto : `zero),
|
||||
]);
|
||||
|
||||
[@react.component]
|
||||
let make = (~height: int) => {
|
||||
let {AudioPlayerProvider.playingState} =
|
||||
AudioPlayerProvider.useAudioPlayer();
|
||||
let artist = playingState.artist;
|
||||
let title = playingState.title;
|
||||
let songTitle = {j|$artist - $title|j};
|
||||
let title =
|
||||
playingState.isPlaying
|
||||
? {j|Beatconnect \u23F5 $songTitle|j} : "Beatconnect";
|
||||
// let window = Remote.getCurrentWindow(Remote.remote);
|
||||
// window->BrowserWindow.setTitle(title);
|
||||
|
||||
// let onMinimizeClick = _e => BrowserWindow.minimize(window);
|
||||
// let onCloseClick = _e => BrowserWindow.close(window);
|
||||
// let onMaximizeClick = _e =>
|
||||
// BrowserWindow.isMaximized(window)
|
||||
// ? BrowserWindow.unmaximize(window) : BrowserWindow.maximize(window);
|
||||
|
||||
let onMinimizeClick = _ => ();
|
||||
let onCloseClick = _ => ();
|
||||
let onMaximizeClick = _ => ();
|
||||
|
||||
<div className={makeWrapperStyle()}>
|
||||
<div
|
||||
className={makeControlStyle(~spacer=true, ())} onClick=onMinimizeClick>
|
||||
{Icon.make(~name="Dash", ~width=height, ~height, ())}
|
||||
</div>
|
||||
<div className={makeControlStyle()} onClick=onMaximizeClick>
|
||||
{Icon.make(~name="Square", ~width=height, ~height, ())}
|
||||
</div>
|
||||
<div className={makeControlStyle(~bgColor=red, ())} onClick=onCloseClick>
|
||||
{Icon.make(~name="Cancel", ~width=height, ~height, ())}
|
||||
</div>
|
||||
</div>;
|
||||
};
|
||||
|
||||
let default = make;
|
||||
@@ -0,0 +1,60 @@
|
||||
open CssJs
|
||||
|
||||
let makeWrapperStyle = () =>
|
||||
style(. [zIndex(500), position(fixed), right(zero), display(#flex), alignItems(center)])
|
||||
|
||||
let makeControlStyle = (~bgColor=?, ~spacer=false, ()) =>
|
||||
style(. [
|
||||
unsafe("WebkitAppRegion", "no-drag"),
|
||||
padding2(~v=zero, ~h=px(7)),
|
||||
selector(.
|
||||
"&:hover",
|
||||
[
|
||||
backgroundColor(
|
||||
switch bgColor {
|
||||
| None => rgba(255, 255, 255, #num(0.25))
|
||||
| Some(c) => c
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
marginLeft(spacer ? #auto : #zero),
|
||||
])
|
||||
|
||||
@react.component
|
||||
let make = (~height: int) => {
|
||||
let {AudioPlayerProvider.playingState: playingState} = AudioPlayerProvider.useAudioPlayer()
|
||||
let artist = playingState.artist
|
||||
let title = playingState.title
|
||||
let songTitle = `${artist} - ${title}`
|
||||
|
||||
let _title = playingState.isPlaying ? `Beatconnect \\u23F5 ${songTitle}bot` : "Beatconnect"
|
||||
|
||||
// let window = Remote.getCurrentWindow(Remote.remote)
|
||||
// window->BrowserWindow.setTitle(title)
|
||||
|
||||
// let onMinimizeClick = _e => BrowserWindow.minimize(window)
|
||||
// let onCloseClick = _e => BrowserWindow.close(window)
|
||||
// let onMaximizeClick = _e =>
|
||||
// BrowserWindow.isMaximized(window)
|
||||
// ? BrowserWindow.unmaximize(window)
|
||||
// : BrowserWindow.maximize(window)
|
||||
|
||||
let onMinimizeClick = _ => ()
|
||||
let onCloseClick = _ => ()
|
||||
let onMaximizeClick = _ => ()
|
||||
|
||||
<div className={makeWrapperStyle()}>
|
||||
<div className={makeControlStyle(~spacer=true, ())} onClick=onMinimizeClick>
|
||||
{Icon.make(~name="Dash", ~width=height, ~height, ())}
|
||||
</div>
|
||||
<div className={makeControlStyle()} onClick=onMaximizeClick>
|
||||
{Icon.make(~name="Square", ~width=height, ~height, ())}
|
||||
</div>
|
||||
<div className={makeControlStyle(~bgColor=red, ())} onClick=onCloseClick>
|
||||
{Icon.make(~name="Cancel", ~width=height, ~height, ())}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
let default = make
|
||||
@@ -51,24 +51,23 @@ type beatmap = {
|
||||
visual_override: bool,
|
||||
last_modification_time_2: float,
|
||||
mania_scroll_speed: int,
|
||||
};
|
||||
}
|
||||
type osuDBData = {
|
||||
beatmaps: list(beatmap),
|
||||
beatmaps: list<beatmap>,
|
||||
userperms: int,
|
||||
isLocked: bool,
|
||||
};
|
||||
type t;
|
||||
[@bs.deriving {jsConverter: newType}]
|
||||
type osuDatabase = [ | `osudb | `collection];
|
||||
}
|
||||
type t
|
||||
@deriving({jsConverter: newType})
|
||||
type osuDatabase = [#osudb | #collection]
|
||||
type osuDbParserInstance = {
|
||||
.
|
||||
[@bs.meth] "getOsuDBData": unit => osuDBData,
|
||||
[@bs.meth] "setBuffer": (abs_osuDatabase, Buffer.t) => unit,
|
||||
};
|
||||
[@bs.new] [@bs.module]
|
||||
external make: unit => osuDbParserInstance = "osu-db-parser";
|
||||
let parser = make();
|
||||
getOsuDBData: unit => osuDBData,
|
||||
setBuffer: (abs_osuDatabase, Buffer.t) => unit,
|
||||
}
|
||||
@new @module
|
||||
external make: unit => osuDbParserInstance = "osu-db-parser"
|
||||
let parser = make()
|
||||
let read = (buffer: Buffer.t) => {
|
||||
parser##setBuffer(osuDatabaseToJs(`osudb), buffer);
|
||||
parser##getOsuDBData();
|
||||
};
|
||||
parser.setBuffer(osuDatabaseToJs(#osudb), buffer)
|
||||
parser.getOsuDBData()
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
let getThumbUrl = beatmapId => {j|https://b.ppy.sh/thumb/$beatmapId.jpg|j};
|
||||
|
||||
let getListCoverUrl = beatmapId => {j|https://assets.ppy.sh/beatmaps/$beatmapId/covers/list@2x.jpg|j};
|
||||
|
||||
let resolveThumbnail = (beatmapId, osuPath, fallbackUrl) => {
|
||||
let localPath =
|
||||
"file://"
|
||||
++ osuPath
|
||||
++ "/Data/bt/"
|
||||
++ beatmapId
|
||||
++ "l.jpg"
|
||||
|> Js_global.encodeURI
|
||||
|> Js_string.replaceByRe([%re "/\\/g/"], "/");
|
||||
|
||||
let thumbanil = Image.make();
|
||||
thumbanil->Image.setSrc(localPath);
|
||||
thumbanil->Image.decode
|
||||
|> Js_promise.then_(() => Js_promise.resolve(localPath))
|
||||
|> Js_promise.catch(_ => Js_promise.resolve(fallbackUrl));
|
||||
};
|
||||
|
||||
let resolveThumbURL = (beatmapId, osuPath) =>
|
||||
resolveThumbnail(beatmapId, osuPath, getListCoverUrl(beatmapId));
|
||||
|
||||
let getBeatmapDifficultyColorHex = (difficulty: float) => {
|
||||
switch (difficulty) {
|
||||
| difficulty when difficulty >= 6.5 => "#000"
|
||||
| difficulty when difficulty >= 5.3 => "#8866ee"
|
||||
| difficulty when difficulty >= 4.0 => "#ff66aa"
|
||||
| difficulty when difficulty >= 2.7 => "#ffcc22"
|
||||
| difficulty when difficulty >= 2.0 => "#66ccff"
|
||||
| _ => "#88b300"
|
||||
};
|
||||
};
|
||||
|
||||
let getBeatmapDifficultyColorRGBA = (difficulty: float) => {
|
||||
switch (difficulty) {
|
||||
| difficulty when difficulty >= 6.5 => Css.rgba(0, 0, 0)
|
||||
| difficulty when difficulty >= 5.3 => Css.rgba(136, 102, 238)
|
||||
| difficulty when difficulty >= 4.0 => Css.rgba(255, 102, 170)
|
||||
| difficulty when difficulty >= 2.7 => Css.rgba(255, 204, 34)
|
||||
| difficulty when difficulty >= 2.0 => Css.rgba(102, 204, 255)
|
||||
| _ => Css.rgba(136, 179, 0)
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
let getThumbUrl = beatmapId => `https://b.ppy.sh/thumb/${beatmapId}.jpg`
|
||||
|
||||
let getListCoverUrl = beatmapId => `https://assets.ppy.sh/beatmaps/${beatmapId}/covers/list@2x.jpg`
|
||||
|
||||
let resolveThumbnail = (beatmapId, osuPath, fallbackUrl) => {
|
||||
let localPath =
|
||||
"file://" ++
|
||||
(osuPath ++ ("/Data/bt/" ++ (beatmapId ++ "l.jpg")))
|
||||
->Js.Global.encodeURI
|
||||
->Js.String2.replaceByRe(%re("/\\/g/"), "/")
|
||||
|
||||
let thumbanil = Image.make()
|
||||
thumbanil->Image.setSrc(localPath)
|
||||
thumbanil->Image.decode
|
||||
|> Js.Promise.then_(() => Js_promise.resolve(localPath))
|
||||
|> Js.Promise.catch(_ => Js_promise.resolve(fallbackUrl))
|
||||
}
|
||||
|
||||
let resolveThumbURL = (beatmapId, osuPath) =>
|
||||
resolveThumbnail(beatmapId, osuPath, getListCoverUrl(beatmapId))
|
||||
|
||||
let getBeatmapDifficultyColorHex = (difficulty: float) =>
|
||||
switch difficulty {
|
||||
| difficulty if difficulty >= 6.5 => "#000"
|
||||
| difficulty if difficulty >= 5.3 => "#8866ee"
|
||||
| difficulty if difficulty >= 4.0 => "#ff66aa"
|
||||
| difficulty if difficulty >= 2.7 => "#ffcc22"
|
||||
| difficulty if difficulty >= 2.0 => "#66ccff"
|
||||
| _ => "#88b300"
|
||||
}
|
||||
|
||||
let getBeatmapDifficultyColorRGBA = (difficulty: float) =>
|
||||
switch difficulty {
|
||||
| difficulty if difficulty >= 6.5 => Css.rgba(0, 0, 0)
|
||||
| difficulty if difficulty >= 5.3 => Css.rgba(136, 102, 238)
|
||||
| difficulty if difficulty >= 4.0 => Css.rgba(255, 102, 170)
|
||||
| difficulty if difficulty >= 2.7 => Css.rgba(255, 204, 34)
|
||||
| difficulty if difficulty >= 2.0 => Css.rgba(102, 204, 255)
|
||||
| _ => Css.rgba(136, 179, 0)
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
type t;
|
||||
type callback('a) = 'a => unit;
|
||||
|
||||
type target = {
|
||||
readyState: int,
|
||||
volume: int,
|
||||
};
|
||||
|
||||
type partialAudioEvent = {target};
|
||||
|
||||
[@bs.new] external make: unit => t = "Audio";
|
||||
[@bs.new] external makeWithSrc: (~src: string) => t = "Audio";
|
||||
|
||||
[@bs.get] external paused: t => bool = "paused";
|
||||
[@bs.get] external getMuted: t => bool = "muted";
|
||||
[@bs.get] external getVolume: t => int = "volume";
|
||||
[@bs.set] external setSrc: (t, string) => unit = "src";
|
||||
[@bs.set] external setVolume: (t, float) => unit = "volume";
|
||||
[@bs.set] external setCurrentTime: (t, int) => unit = "currentTime";
|
||||
[@bs.set] external setMuted: (t, bool) => unit = "muted";
|
||||
[@bs.send] external pause: t => unit = "pause";
|
||||
[@bs.send] external play: t => unit = "play";
|
||||
[@bs.set]
|
||||
external onended: (t, callback(partialAudioEvent)) => unit = "onended";
|
||||
[@bs.set]
|
||||
external onerror: (t, callback(partialAudioEvent)) => unit = "onerror";
|
||||
[@bs.set]
|
||||
external onpause: (t, callback(partialAudioEvent)) => unit = "onpause";
|
||||
[@bs.set]
|
||||
external onplay: (t, callback(partialAudioEvent)) => unit = "onplay";
|
||||
[@bs.set]
|
||||
external oncanplay: (t, callback(partialAudioEvent)) => unit = "oncanplay";
|
||||
[@bs.set]
|
||||
external onvolumechange: (t, callback(partialAudioEvent)) => unit =
|
||||
"onvolumechange";
|
||||
@@ -0,0 +1,34 @@
|
||||
type t
|
||||
type callback<'a> = 'a => unit
|
||||
|
||||
type target = {
|
||||
readyState: int,
|
||||
volume: int,
|
||||
}
|
||||
|
||||
type partialAudioEvent = {target: target}
|
||||
|
||||
@new external make: unit => t = "Audio"
|
||||
@new external makeWithSrc: (~src: string) => t = "Audio"
|
||||
|
||||
@get external paused: t => bool = "paused"
|
||||
@get external getMuted: t => bool = "muted"
|
||||
@get external getVolume: t => int = "volume"
|
||||
@set external setSrc: (t, string) => unit = "src"
|
||||
@set external setVolume: (t, float) => unit = "volume"
|
||||
@set external setCurrentTime: (t, int) => unit = "currentTime"
|
||||
@set external setMuted: (t, bool) => unit = "muted"
|
||||
@send external pause: t => unit = "pause"
|
||||
@send external play: t => unit = "play"
|
||||
@set
|
||||
external onended: (t, callback<partialAudioEvent>) => unit = "onended"
|
||||
@set
|
||||
external onerror: (t, callback<partialAudioEvent>) => unit = "onerror"
|
||||
@set
|
||||
external onpause: (t, callback<partialAudioEvent>) => unit = "onpause"
|
||||
@set
|
||||
external onplay: (t, callback<partialAudioEvent>) => unit = "onplay"
|
||||
@set
|
||||
external oncanplay: (t, callback<partialAudioEvent>) => unit = "oncanplay"
|
||||
@set
|
||||
external onvolumechange: (t, callback<partialAudioEvent>) => unit = "onvolumechange"
|
||||
@@ -1,7 +0,0 @@
|
||||
type t;
|
||||
|
||||
[@bs.new] external make: unit => t = "Image";
|
||||
[@bs.new] external makeWithSize: (~width: int, ~height: int) => t = "Image";
|
||||
|
||||
[@bs.send] external decode: t => Js.Promise.t(unit) = "decode";
|
||||
[@bs.set] external setSrc: (t, string) => unit = "src";
|
||||
@@ -0,0 +1,7 @@
|
||||
type t
|
||||
|
||||
@new external make: unit => t = "Image"
|
||||
@new external makeWithSize: (~width: int, ~height: int) => t = "Image"
|
||||
|
||||
@send external decode: t => Js.Promise.t<unit> = "decode"
|
||||
@set external setSrc: (t, string) => unit = "src"
|
||||
@@ -1,22 +1,22 @@
|
||||
type t;
|
||||
type t
|
||||
|
||||
type artwork = {
|
||||
src: string,
|
||||
sizes: string,
|
||||
type_: string,
|
||||
};
|
||||
}
|
||||
|
||||
type metadata = {
|
||||
title: string,
|
||||
artist: string,
|
||||
album: string,
|
||||
artwork: array(artwork),
|
||||
};
|
||||
artwork: array<artwork>,
|
||||
}
|
||||
|
||||
[@bs.new] external make: metadata => t = "MediaMetadata";
|
||||
@new external make: metadata => t = "MediaMetadata"
|
||||
|
||||
let makeArtwork = id => {
|
||||
src: PpyHelpers.getListCoverUrl(id),
|
||||
sizes: "160x100",
|
||||
type_: "image/jpg",
|
||||
};
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
type t;
|
||||
type navigator;
|
||||
|
||||
[@bs.deriving {jsConverter: newType}]
|
||||
type actionType = [ | `play | `pause | `previoustrack | `nexttrack | `stop];
|
||||
|
||||
[@bs.val] external mediaSession: t = "navigator.mediaSession";
|
||||
|
||||
[@bs.val] external navigator: navigator = "navigator";
|
||||
|
||||
[@bs.send]
|
||||
external setActionHandler: (t, actionType, option(unit => unit)) => unit =
|
||||
"setActionHandler";
|
||||
|
||||
let setActionHandler = setActionHandler(mediaSession);
|
||||
|
||||
[@bs.set]
|
||||
external setMediaSessionMetadata: (t, MediaMetadata.t) => unit = "metadata";
|
||||
|
||||
let setMediaSessionMetadata = setMediaSessionMetadata(mediaSession);
|
||||
@@ -0,0 +1,19 @@
|
||||
type t
|
||||
type navigator
|
||||
|
||||
@deriving({jsConverter: newType})
|
||||
type actionType = [#play | #pause | #previoustrack | #nexttrack | #stop]
|
||||
|
||||
@val external mediaSession: t = "navigator.mediaSession"
|
||||
|
||||
@val external navigator: navigator = "navigator"
|
||||
|
||||
@send
|
||||
external setActionHandler: (t, actionType, option<unit => unit>) => unit = "setActionHandler"
|
||||
|
||||
let setActionHandler = setActionHandler(mediaSession)
|
||||
|
||||
@set
|
||||
external setMediaSessionMetadata: (t, MediaMetadata.t) => unit = "metadata"
|
||||
|
||||
let setMediaSessionMetadata = setMediaSessionMetadata(mediaSession)
|
||||
@@ -1,8 +0,0 @@
|
||||
type t;
|
||||
|
||||
[@bs.send] external setTitle: (t, string) => unit = "setTitle";
|
||||
[@bs.send] external isMaximized: t => bool = "isMaximized";
|
||||
[@bs.send] external unmaximize: t => unit = "unmaximize";
|
||||
[@bs.send] external maximize: t => unit = "maximize";
|
||||
[@bs.send] external close: t => unit = "close";
|
||||
[@bs.send] external minimize: t => unit = "minimize";
|
||||
@@ -0,0 +1,8 @@
|
||||
type t
|
||||
|
||||
@send external setTitle: (t, string) => unit = "setTitle"
|
||||
@send external isMaximized: t => bool = "isMaximized"
|
||||
@send external unmaximize: t => unit = "unmaximize"
|
||||
@send external maximize: t => unit = "maximize"
|
||||
@send external close: t => unit = "close"
|
||||
@send external minimize: t => unit = "minimize"
|
||||
@@ -1,29 +0,0 @@
|
||||
type t;
|
||||
[@bs.module "electron"] external remote: t = "ipcRenderer";
|
||||
|
||||
[@bs.send] external send: (t, string, 'a) => unit = "send";
|
||||
[@bs.send] external on: (t, string, 'a => unit) => unit = "on";
|
||||
[@bs.send]
|
||||
external removeListener: (t, string, 'a => unit) => unit = "removeListener";
|
||||
|
||||
type updateThumbBarData = {
|
||||
isPlaying: bool,
|
||||
canPlayNext: bool,
|
||||
canPlayPrev: bool,
|
||||
};
|
||||
|
||||
type channel =
|
||||
| UPDATE_THUMB_BAR(updateThumbBarData)
|
||||
| UPDATE_PLAY_STATE(bool);
|
||||
|
||||
let send = channel => {
|
||||
switch (channel) {
|
||||
| UPDATE_THUMB_BAR(data) => send(remote, "UPDATE_THUMB_BAR", data)
|
||||
| UPDATE_PLAY_STATE(isPlaying) =>
|
||||
send(remote, "UPDATE_PLAY_STATE", isPlaying)
|
||||
};
|
||||
};
|
||||
|
||||
let on = (channel, callback) => on(remote, channel, callback);
|
||||
let removeListener = (channel, callback) =>
|
||||
removeListener(remote, channel, callback);
|
||||
@@ -0,0 +1,26 @@
|
||||
type t
|
||||
@module("electron") external remote: t = "ipcRenderer"
|
||||
|
||||
@send external send: (t, string, 'a) => unit = "send"
|
||||
@send external on: (t, string, 'a => unit) => unit = "on"
|
||||
@send
|
||||
external removeListener: (t, string, 'a => unit) => unit = "removeListener"
|
||||
|
||||
type updateThumbBarData = {
|
||||
isPlaying: bool,
|
||||
canPlayNext: bool,
|
||||
canPlayPrev: bool,
|
||||
}
|
||||
|
||||
type channel =
|
||||
| UPDATE_THUMB_BAR(updateThumbBarData)
|
||||
| UPDATE_PLAY_STATE(bool)
|
||||
|
||||
let send = channel =>
|
||||
switch channel {
|
||||
| UPDATE_THUMB_BAR(data) => send(remote, "UPDATE_THUMB_BAR", data)
|
||||
| UPDATE_PLAY_STATE(isPlaying) => send(remote, "UPDATE_PLAY_STATE", isPlaying)
|
||||
}
|
||||
|
||||
let on = (channel, callback) => on(remote, channel, callback)
|
||||
let removeListener = (channel, callback) => removeListener(remote, channel, callback)
|
||||
@@ -1,5 +0,0 @@
|
||||
type t;
|
||||
|
||||
[@bs.module "electron"] external remote: t = "remote";
|
||||
[@bs.send]
|
||||
external getCurrentWindow: t => BrowserWindow.t = "getCurrentWindow";
|
||||
@@ -0,0 +1,5 @@
|
||||
type t
|
||||
|
||||
@module("electron") external remote: t = "remote"
|
||||
@send
|
||||
external getCurrentWindow: t => BrowserWindow.t = "getCurrentWindow"
|
||||
@@ -249,7 +249,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.12.13, @babel/helper-module-imports@npm:^7.16.7":
|
||||
"@babel/helper-module-imports@npm:^7.12.13, @babel/helper-module-imports@npm:^7.16.7":
|
||||
version: 7.16.7
|
||||
resolution: "@babel/helper-module-imports@npm:7.16.7"
|
||||
dependencies:
|
||||
@@ -290,6 +290,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-plugin-utils@npm:^7.17.12":
|
||||
version: 7.17.12
|
||||
resolution: "@babel/helper-plugin-utils@npm:7.17.12"
|
||||
checksum: 300da74658e2b958bb488d4ca27757e676b14f9978501dfb3a2fc505d4322d58fbd4f7b79470299828f61cf880dff8fce83bbe942f0a00e0b86a8fdc21f6cc8d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-remap-async-to-generator@npm:^7.16.8":
|
||||
version: 7.16.8
|
||||
resolution: "@babel/helper-remap-async-to-generator@npm:7.16.8"
|
||||
@@ -735,6 +742,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/plugin-syntax-jsx@npm:^7.12.13":
|
||||
version: 7.17.12
|
||||
resolution: "@babel/plugin-syntax-jsx@npm:7.17.12"
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils": ^7.17.12
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0-0
|
||||
checksum: a5dde0b0fc6493a4b1f0341a7b68dcfa0c1ba1553e8aa21e995320cb4267df619c7c20c0840f14f13c302f4bef4759a92cde3f69c0be1ff489dcc2835bc4de53
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/plugin-syntax-jsx@npm:^7.16.7":
|
||||
version: 7.16.7
|
||||
resolution: "@babel/plugin-syntax-jsx@npm:7.16.7"
|
||||
@@ -1471,6 +1489,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.13.10":
|
||||
version: 7.18.3
|
||||
resolution: "@babel/runtime@npm:7.18.3"
|
||||
dependencies:
|
||||
regenerator-runtime: ^0.13.4
|
||||
checksum: 70aa471de7452e9ad6d1f7ef880b76558b102a97d81aaf3251a6d70b90de7388ac0e7f5a9f5b5266ee046df92451cd7e1b310c043a5f131704949138d4790643
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/template@npm:^7.12.13, @babel/template@npm:^7.16.7, @babel/template@npm:^7.3.3, @babel/template@npm:^7.4.0":
|
||||
version: 7.16.7
|
||||
resolution: "@babel/template@npm:7.16.7"
|
||||
@@ -1576,19 +1603,60 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/cache@npm:^10.0.27":
|
||||
version: 10.0.29
|
||||
resolution: "@emotion/cache@npm:10.0.29"
|
||||
"@emotion/babel-plugin@npm:^11.7.1":
|
||||
version: 11.9.2
|
||||
resolution: "@emotion/babel-plugin@npm:11.9.2"
|
||||
dependencies:
|
||||
"@emotion/sheet": 0.9.4
|
||||
"@emotion/stylis": 0.8.5
|
||||
"@emotion/utils": 0.11.3
|
||||
"@emotion/weak-memoize": 0.2.5
|
||||
checksum: a2bdf4dd21b63d5e88999bfefe841e5a7c64783d321f94bb930d28d18e8d15c80997c84a21996856d9356ef36d70e1ea1209f23de0c2f9e65c8b86e7d3a2f192
|
||||
"@babel/helper-module-imports": ^7.12.13
|
||||
"@babel/plugin-syntax-jsx": ^7.12.13
|
||||
"@babel/runtime": ^7.13.10
|
||||
"@emotion/hash": ^0.8.0
|
||||
"@emotion/memoize": ^0.7.5
|
||||
"@emotion/serialize": ^1.0.2
|
||||
babel-plugin-macros: ^2.6.1
|
||||
convert-source-map: ^1.5.0
|
||||
escape-string-regexp: ^4.0.0
|
||||
find-root: ^1.1.0
|
||||
source-map: ^0.5.7
|
||||
stylis: 4.0.13
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
checksum: 5956bc9eefe556c95323b198aa337abdcca30bc0624c3cae93378f262bded7992582a7e7d2f86868dbd3a831f7ae78b79714e9a36a124e1f6763d8706d4716ad
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/hash@npm:0.8.0":
|
||||
"@emotion/cache@npm:^11.0.0, @emotion/cache@npm:^11.7.1":
|
||||
version: 11.7.1
|
||||
resolution: "@emotion/cache@npm:11.7.1"
|
||||
dependencies:
|
||||
"@emotion/memoize": ^0.7.4
|
||||
"@emotion/sheet": ^1.1.0
|
||||
"@emotion/utils": ^1.0.0
|
||||
"@emotion/weak-memoize": ^0.2.5
|
||||
stylis: 4.0.13
|
||||
checksum: 60b5ce3fcc9caafa4d6a3c72079f1e4051bdfd50c44321f6263555cf5f6acc07706da5328615c1b0b52fa0dd7cf4a41bcf2ee1aae45b7aa25ad73d867f720189
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/css@npm:^11.0.0":
|
||||
version: 11.9.0
|
||||
resolution: "@emotion/css@npm:11.9.0"
|
||||
dependencies:
|
||||
"@emotion/babel-plugin": ^11.7.1
|
||||
"@emotion/cache": ^11.7.1
|
||||
"@emotion/serialize": ^1.0.3
|
||||
"@emotion/sheet": ^1.0.3
|
||||
"@emotion/utils": ^1.0.0
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
peerDependenciesMeta:
|
||||
"@babel/core":
|
||||
optional: true
|
||||
checksum: 4c835e473e9dff1b9017fb6e782a356bb5b7593ef7f4c11f5827288f25ecdb970456f258c65bfa3cc7a48e6de0eea8287df605d1d8cda4b476fd5da7388e1789
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/hash@npm:^0.8.0":
|
||||
version: 0.8.0
|
||||
resolution: "@emotion/hash@npm:0.8.0"
|
||||
checksum: 8fd781e18428745d6c7121bebf3965cad12c61f3bd5fb773e46f16f1d7b7ae1346770df438fcfe8bc73ecf6762a54baef7cf259a694575d4f06cabb79ebcf7c0
|
||||
@@ -1611,55 +1679,48 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/memoize@npm:0.7.4":
|
||||
version: 0.7.4
|
||||
resolution: "@emotion/memoize@npm:0.7.4"
|
||||
checksum: 874123a94c89963dda3438d1ea7f7c17fa670d965610eefaa49e0dbf47cccee6f6108e04175867d7e485d2c04096a98bba5a4bef2606b3bf2070637327ebe3ff
|
||||
"@emotion/memoize@npm:^0.7.4, @emotion/memoize@npm:^0.7.5":
|
||||
version: 0.7.5
|
||||
resolution: "@emotion/memoize@npm:0.7.5"
|
||||
checksum: 09f5290283c50ae32f0808bebacf7eaac7ecdbd799a27698479bd03821f3acbd2ac512adcf0ae43394fed804007d6cd18de0c49475a14cd020d5f18fc7ab72bf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/serialize@npm:^0.11.15, @emotion/serialize@npm:^0.11.16":
|
||||
version: 0.11.16
|
||||
resolution: "@emotion/serialize@npm:0.11.16"
|
||||
"@emotion/serialize@npm:^1.0.2, @emotion/serialize@npm:^1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "@emotion/serialize@npm:1.0.3"
|
||||
dependencies:
|
||||
"@emotion/hash": 0.8.0
|
||||
"@emotion/memoize": 0.7.4
|
||||
"@emotion/unitless": 0.7.5
|
||||
"@emotion/utils": 0.11.3
|
||||
csstype: ^2.5.7
|
||||
checksum: b7d9a94a039ea5e86b0daccc29f0c40fbbda7004b1fde9ee14be38463c3aaabdd027b38c5c0e580f66883fb6e3b49160292843b0e14efe49e662a520c38f4c15
|
||||
"@emotion/hash": ^0.8.0
|
||||
"@emotion/memoize": ^0.7.4
|
||||
"@emotion/unitless": ^0.7.5
|
||||
"@emotion/utils": ^1.0.0
|
||||
csstype: ^3.0.2
|
||||
checksum: 4a02aaa3594cd2821f887212eb989459aea90bc47b166a1337838b76392267408dffb49b90e4d9dcb5a2b80e34ec71f0c9aea401a830604f93b7e2358c78ce2c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/sheet@npm:0.9.4":
|
||||
version: 0.9.4
|
||||
resolution: "@emotion/sheet@npm:0.9.4"
|
||||
checksum: 48baa183e56d78df56ad474d833476fc26c0d563e931a82245e38975fe47ed338155d73dd5769c675aa821feef2e0480f4285c0584fc5271026f276316a299c1
|
||||
"@emotion/sheet@npm:^1.0.3, @emotion/sheet@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "@emotion/sheet@npm:1.1.0"
|
||||
checksum: 9ffd9df2a86d0bf2b23b489adaebb38ec763be91772a25547164ed5058910270f59dc8fb8c181f2da000231deb35fc4b9cf31c00f70e15fb1ce89c76053f7f5f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/stylis@npm:0.8.5":
|
||||
version: 0.8.5
|
||||
resolution: "@emotion/stylis@npm:0.8.5"
|
||||
checksum: bb43a77f784cce86f7a625519544aab56b8f341117957f7dd15315398780289784bd2ec0ba1bc1b19ac639bdb304a4ed08b1f8e3e4c13e8063b9824e551b3994
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/unitless@npm:0.7.5":
|
||||
"@emotion/unitless@npm:^0.7.5":
|
||||
version: 0.7.5
|
||||
resolution: "@emotion/unitless@npm:0.7.5"
|
||||
checksum: 0be366ef09860037ef08aed0450cb5510f4be25886005e2f120f8e8b7385de6b41ac47df5b9bd55781e5153853e9ed5f49aa517dcbad34cc23bd8afb0201932a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/utils@npm:0.11.3":
|
||||
version: 0.11.3
|
||||
resolution: "@emotion/utils@npm:0.11.3"
|
||||
checksum: b5c3a22204a878eafa8deb362493b48c3f3a7f7ec3e5a18634d14aa8d5c9d8274db0a9d0206b3c124fa170640880fbcda987971699a1cf69355f2cec994da487
|
||||
"@emotion/utils@npm:^1.0.0":
|
||||
version: 1.1.0
|
||||
resolution: "@emotion/utils@npm:1.1.0"
|
||||
checksum: ab04aafa16c7c3e0b98a68f10ca388edd4af0ca299861dc700c1b02f44e0a355f9af6732250a2772e572c607100abe6f09eec19a9a9631f50d5866c11750830a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/weak-memoize@npm:0.2.5":
|
||||
"@emotion/weak-memoize@npm:^0.2.5":
|
||||
version: 0.2.5
|
||||
resolution: "@emotion/weak-memoize@npm:0.2.5"
|
||||
checksum: 9fe31f0c9d761468d7868be2faf924ddef3506160c72a1979ced8f72cec5d90499403a29c904af570496ef06803e484495f84d4c311bd0787259c89dba4119ed
|
||||
@@ -2147,6 +2208,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@rescript/react@npm:0.10.3":
|
||||
version: 0.10.3
|
||||
resolution: "@rescript/react@npm:0.10.3"
|
||||
peerDependencies:
|
||||
react: ">=16.8.1"
|
||||
react-dom: ">=16.8.1"
|
||||
checksum: 8b3ab98ed0b9122b878a4d3bf01ac2657059ad89642204948057bd822b0ff01c4631e113d57e9bf75b01fbe63a2f8dec149121643c9c3a47d9532d853fd07835
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sindresorhus/is@npm:^0.14.0":
|
||||
version: 0.14.0
|
||||
resolution: "@sindresorhus/is@npm:0.14.0"
|
||||
@@ -3639,24 +3710,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"babel-plugin-emotion@npm:^10.0.27":
|
||||
version: 10.2.2
|
||||
resolution: "babel-plugin-emotion@npm:10.2.2"
|
||||
dependencies:
|
||||
"@babel/helper-module-imports": ^7.0.0
|
||||
"@emotion/hash": 0.8.0
|
||||
"@emotion/memoize": 0.7.4
|
||||
"@emotion/serialize": ^0.11.16
|
||||
babel-plugin-macros: ^2.0.0
|
||||
babel-plugin-syntax-jsx: ^6.18.0
|
||||
convert-source-map: ^1.5.0
|
||||
escape-string-regexp: ^1.0.5
|
||||
find-root: ^1.1.0
|
||||
source-map: ^0.5.7
|
||||
checksum: 6def612598c8dbb74942271b8cb406eccad0d1a6b4ec1180f8205f5e92362b3e200bc566fdec58e37076a6a602e95c226fc9d28ed6a558fff748637cb214e3c9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"babel-plugin-istanbul@npm:^5.1.0":
|
||||
version: 5.2.0
|
||||
resolution: "babel-plugin-istanbul@npm:5.2.0"
|
||||
@@ -3694,7 +3747,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"babel-plugin-macros@npm:^2.0.0":
|
||||
"babel-plugin-macros@npm:^2.6.1":
|
||||
version: 2.8.0
|
||||
resolution: "babel-plugin-macros@npm:2.8.0"
|
||||
dependencies:
|
||||
@@ -3761,13 +3814,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"babel-plugin-syntax-jsx@npm:^6.18.0":
|
||||
version: 6.18.0
|
||||
resolution: "babel-plugin-syntax-jsx@npm:6.18.0"
|
||||
checksum: a5c8174ad6165d5f541f9f31cf4b6338ccfb7d586cec111537fa567f13b5fbdcf54f7928db44429d4610aa1be9d07bb03d017b22ba521ff819a6a2090b694797
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"babel-plugin-transform-react-remove-prop-types@npm:^0.4.24":
|
||||
version: 0.4.24
|
||||
resolution: "babel-plugin-transform-react-remove-prop-types@npm:0.4.24"
|
||||
@@ -3884,6 +3930,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@babel/core": 7.13.13
|
||||
"@babel/preset-env": ^7.13.12
|
||||
"@rescript/react": 0.10.3
|
||||
"@svgr/webpack": 5.5.0
|
||||
acorn-dynamic-import: ^4.0.0
|
||||
babel-eslint: 10.1.0
|
||||
@@ -3891,8 +3938,8 @@ __metadata:
|
||||
babel-loader: 8.2.2
|
||||
babel-plugin-named-asset-import: ^0.3.7
|
||||
babel-preset-react-app: ^10.0.0
|
||||
bs-css: ^11.0.0
|
||||
bs-platform: 8.4.2
|
||||
bs-css: ^15.3.0
|
||||
bs-css-emotion: ^4.3.0
|
||||
camelcase: ^5.2.0
|
||||
case-sensitive-paths-webpack-plugin: 2.3.0
|
||||
conventional-changelog-cli: ^2.1.1
|
||||
@@ -3939,8 +3986,8 @@ __metadata:
|
||||
react-jss: ^10.6.0
|
||||
react-redux: ^7.2.3
|
||||
react-window: ^1.8.6
|
||||
reason-react: ^0.7.1
|
||||
redux: ^4.0.5
|
||||
rescript: 9.1.4
|
||||
resolve: 1.17.0
|
||||
semver: 6.0.0
|
||||
string-replace-loader: ^2.3.0
|
||||
@@ -4230,24 +4277,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bs-css@npm:^11.0.0":
|
||||
version: 11.0.0
|
||||
resolution: "bs-css@npm:11.0.0"
|
||||
"bs-css-emotion@npm:^4.3.0":
|
||||
version: 4.3.0
|
||||
resolution: "bs-css-emotion@npm:4.3.0"
|
||||
dependencies:
|
||||
emotion: ^10.0.7
|
||||
checksum: 299817a12c9d21d91b43d9309c738ff8e269eaa1f89fe725fc36dbd570072d65dfcad8a086994594b7e5ce4fc3a136ec1a36a16de612032a4cb2fc5184b6d26d
|
||||
"@emotion/cache": ^11.0.0
|
||||
"@emotion/css": ^11.0.0
|
||||
bs-css: 15.3.0
|
||||
checksum: df84803a9a8716010778999daf9283de29268ca1fcbaa558a95b312ba811f7c701845230bd2f50f6c19424528e8c3484c344d2ec702542687f32bdc9ab5f3c11
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bs-platform@npm:8.4.2":
|
||||
version: 8.4.2
|
||||
resolution: "bs-platform@npm:8.4.2"
|
||||
bin:
|
||||
bsb: bsb
|
||||
bsc: bsc
|
||||
bsrefmt: bsrefmt
|
||||
bstracing: lib/bstracing
|
||||
checksum: 60f84c4c63809031d2e8609f90ef877174b9461d8ca8e3697c921548648a7187ddc977ce210dd2df91568c5ffc46a8ffe16dcf8836ddb6637d6dcbaaef306a08
|
||||
"bs-css@npm:15.3.0, bs-css@npm:^15.3.0":
|
||||
version: 15.3.0
|
||||
resolution: "bs-css@npm:15.3.0"
|
||||
checksum: 0b9b954541dd48d5b0d3accaad222c110d905725c7356f3dfd695296d75582ae976904fb80dedddbe1864803ef9cf6e221fbb6b4508e7740134da8bc0e4d5392
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -5465,18 +5509,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"create-emotion@npm:^10.0.27":
|
||||
version: 10.0.27
|
||||
resolution: "create-emotion@npm:10.0.27"
|
||||
dependencies:
|
||||
"@emotion/cache": ^10.0.27
|
||||
"@emotion/serialize": ^0.11.15
|
||||
"@emotion/sheet": 0.9.4
|
||||
"@emotion/utils": 0.11.3
|
||||
checksum: 59581a54fe4f6da6bcbae502df852f0cf0dc6f002aaf416701266a4d944e63d9e33ac0d733b35d8a6265f4052dfdba67222ae341e8f9382afb2e40ed03831053
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "create-hash@npm:1.2.0"
|
||||
@@ -5694,13 +5726,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"csstype@npm:^2.5.7":
|
||||
version: 2.6.20
|
||||
resolution: "csstype@npm:2.6.20"
|
||||
checksum: 6f7ec09b01460f266d32b6963c386c0412b29775db5a1137986c85daf5df8db395d4b04d5e10b57f358e838fec278c9361263be7a675c67efa4fcb873fa073b3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"csstype@npm:^3.0.2":
|
||||
version: 3.0.11
|
||||
resolution: "csstype@npm:3.0.11"
|
||||
@@ -6507,16 +6532,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"emotion@npm:^10.0.7":
|
||||
version: 10.0.27
|
||||
resolution: "emotion@npm:10.0.27"
|
||||
dependencies:
|
||||
babel-plugin-emotion: ^10.0.27
|
||||
create-emotion: ^10.0.27
|
||||
checksum: cc542b2df96732b0c60683a60c94e42d226ac37854c73d33c6e32f596dce52261a4c07a841edf621f44166a4b5a146e4cb18d294ae6759a5522f80e2dba5cd44
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"encodeurl@npm:^1.0.2, encodeurl@npm:~1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "encodeurl@npm:1.0.2"
|
||||
@@ -13082,7 +13097,7 @@ fsevents@^1.2.7:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-dom@npm:>=16.8.1, react-dom@npm:^17.0.2":
|
||||
"react-dom@npm:^17.0.2":
|
||||
version: 17.0.2
|
||||
resolution: "react-dom@npm:17.0.2"
|
||||
dependencies:
|
||||
@@ -13171,7 +13186,7 @@ fsevents@^1.2.7:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react@npm:>=16.8.1, react@npm:^17.0.2":
|
||||
"react@npm:^17.0.2":
|
||||
version: 17.0.2
|
||||
resolution: "react@npm:17.0.2"
|
||||
dependencies:
|
||||
@@ -13303,16 +13318,6 @@ fsevents@^1.2.7:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"reason-react@npm:^0.7.1":
|
||||
version: 0.7.1
|
||||
resolution: "reason-react@npm:0.7.1"
|
||||
dependencies:
|
||||
react: ">=16.8.1"
|
||||
react-dom: ">=16.8.1"
|
||||
checksum: 66f0aa4817ad90db10e61dd18e7e6c5ee517dd54f6ad39c69cfdcfba03aecc2e330a3299fd735a3e7c781ae8f0b7b818c1eabcd42b38abae4eb23db3ddbece16
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"recursive-readdir@npm:2.2.2":
|
||||
version: 2.2.2
|
||||
resolution: "recursive-readdir@npm:2.2.2"
|
||||
@@ -13571,6 +13576,18 @@ fsevents@^1.2.7:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rescript@npm:9.1.4":
|
||||
version: 9.1.4
|
||||
resolution: "rescript@npm:9.1.4"
|
||||
bin:
|
||||
bsc: bsc
|
||||
bsrefmt: bsrefmt
|
||||
bstracing: lib/bstracing
|
||||
rescript: rescript
|
||||
checksum: 96638bedf42159713b67dde4cd7c2008775f1f310ba41f65d879521983a011bcfbfb7ab0b404af9084ff25ccedc14f2289de8805002fe95154a11e75cbe87145
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve-cwd@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "resolve-cwd@npm:2.0.0"
|
||||
@@ -14859,6 +14876,13 @@ resolve@^2.0.0-next.3:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stylis@npm:4.0.13":
|
||||
version: 4.0.13
|
||||
resolution: "stylis@npm:4.0.13"
|
||||
checksum: 2c91ba8bd0de9c210d7a8ef94a0fbbef954f3e64af7185e21f6aa003d27d56f5073a7fb09075857e6ea056ca6c56feb8e55e8e9ddf44cea0f58d76e3b07fc3a8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sumchecker@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "sumchecker@npm:3.0.1"
|
||||
|
||||
Reference in New Issue
Block a user