118 lines
5.4 KiB
Markdown
118 lines
5.4 KiB
Markdown
For reference, the source code is in `~/src/rithik-b/PlaylistManager`.
|
||
|
||
Here is how “add this map to a playlist” is wired in this repo.
|
||
|
||
### 1. User clicks Add (opens the picker)
|
||
|
||
The Add button on the level detail screen calls `AddPlaylistModalController.ShowModal()`:
|
||
|
||
```64:70:PlaylistManager/UI/ViewControllers/LevelDetailButtonsViewController.cs
|
||
[UIAction("add-button-click")]
|
||
private void OpenAddModal()
|
||
{
|
||
addPlaylistController.ShowModal();
|
||
}
|
||
```
|
||
|
||
`ShowModal` parses the BSML if needed, opens the modal, and lists playlists from the default lib manager:
|
||
|
||
```97:103:PlaylistManager/UI/ViewControllers/AddPlaylistModalController.cs
|
||
internal void ShowModal()
|
||
{
|
||
Parse();
|
||
parserParams.EmitEvent("close-modal");
|
||
parserParams.EmitEvent("open-modal");
|
||
ShowPlaylistsForManager(PlaylistLibUtils.playlistManager);
|
||
}
|
||
```
|
||
|
||
### 2. User picks a playlist row — that is where the map is actually added
|
||
|
||
The real work is in `AddPlaylistModalController.OnCellSelect`: after navigating folders, choosing a playlist calls **`IPlaylist.Add(...)`** from **BeatSaberPlaylistsLib**, then persists and notifies:
|
||
|
||
```165:204:PlaylistManager/UI/ViewControllers/AddPlaylistModalController.cs
|
||
[UIAction("select-cell")]
|
||
private void OnCellSelect(TableView tableView, int index)
|
||
{
|
||
playlistTableData.TableView.ClearSelection();
|
||
// Folder Selected
|
||
if (index < childManagers.Count)
|
||
{
|
||
ShowPlaylistsForManager(childManagers[index]);
|
||
}
|
||
else
|
||
{
|
||
index -= childManagers.Count;
|
||
var selectedPlaylist = childPlaylists[index];
|
||
IPlaylistSong playlistSong;
|
||
if (HighlightDifficulty)
|
||
{
|
||
playlistSong = selectedPlaylist.Add(standardLevelDetailViewController.beatmapLevel, standardLevelDetailViewController.beatmapKey);
|
||
}
|
||
else
|
||
{
|
||
playlistSong = selectedPlaylist.Add(standardLevelDetailViewController.beatmapLevel);
|
||
}
|
||
try
|
||
{
|
||
selectedPlaylist.RaisePlaylistChanged();
|
||
parentManager.StorePlaylist(selectedPlaylist);
|
||
popupModalsController.ShowOkModal(modalTransform, string.Format("Song successfully added to {0}", selectedPlaylist.Title), null, animateParentCanvas: false);
|
||
// TODO: Doesn't refresh the sprite.
|
||
Events.RaisePlaylistSongAdded(playlistSong, selectedPlaylist);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
popupModalsController.ShowOkModal(modalTransform, "An error occured while adding song to playlist.", null, animateParentCanvas: false);
|
||
Plugin.Log.Critical(string.Format("An exception was thrown while adding a song to a playlist.\nException Message: {0}", e.Message));
|
||
}
|
||
finally
|
||
{
|
||
ShowPlaylistsForManager(parentManager);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
So:
|
||
|
||
- **PlaylistManager code**: `AddPlaylistModalController.OnCellSelect` (orchestration, UI, `StorePlaylist`, `Events.RaisePlaylistSongAdded`).
|
||
- **Library code**: `selectedPlaylist.Add(...)` — implementation of how the entry is stored lives in **BeatSaberPlaylistsLib** (`IPlaylist`), not in this repository.
|
||
|
||
There is no other `.Add(` on a playlist for this flow in the grep results; removing a song is the parallel path in `LevelDetailButtonsViewController.RemoveSong()`.
|
||
|
||
## hooking into the process
|
||
|
||
### 1. Subscribe to PlaylistManager’s public event (simplest)
|
||
|
||
After a successful add from the **Add to playlist** UI, PlaylistManager raises a **public static** event:
|
||
|
||
```16:18:PlaylistManager/Utilities/Events.cs
|
||
/// <summary>
|
||
/// Raised when an <see cref="BeatSaberPlaylistsLib.Types.IPlaylistSong"/> is added to an <see cref="BeatSaberPlaylistsLib.Types.IPlaylist"/>
|
||
/// </summary>
|
||
public static event Action<BeatSaberPlaylistsLib.Types.IPlaylistSong, BeatSaberPlaylistsLib.Types.IPlaylist> playlistSongAdded;
|
||
```
|
||
|
||
It is invoked **after** `RaisePlaylistChanged()` and `StorePlaylist()` succeed:
|
||
|
||
```187:194:PlaylistManager/UI/ViewControllers/AddPlaylistModalController.cs
|
||
try
|
||
{
|
||
selectedPlaylist.RaisePlaylistChanged();
|
||
parentManager.StorePlaylist(selectedPlaylist);
|
||
popupModalsController.ShowOkModal(modalTransform, string.Format("Song successfully added to {0}", selectedPlaylist.Title), null, animateParentCanvas: false);
|
||
// TODO: Doesn't refresh the sprite.
|
||
Events.RaisePlaylistSongAdded(playlistSong, selectedPlaylist);
|
||
}
|
||
```
|
||
|
||
In your plugin: add a **reference to `PlaylistManager.dll`**, a **manifest dependency** on PlaylistManager, then subscribe in `OnEnable` (or menu init) and unsubscribe in `OnDisable`:
|
||
|
||
- Namespace: `PlaylistManager.Utilities`
|
||
- Type: `Events`
|
||
- Event: `playlistSongAdded`
|
||
- Handler signature: `(IPlaylistSong song, IPlaylist playlist)` from `BeatSaberPlaylistsLib.Types`
|
||
|
||
**Caveat:** This is only raised for adds that go through **this** code path. It is the **only** `RaisePlaylistSongAdded` call site in the repo, so adds done only via BeatSaberPlaylistsLib (or another mod) will **not** fire this event.
|