From 1a76699afc81d858900f140db238005a8c5da1fd Mon Sep 17 00:00:00 2001
From: talwat <83217276+talwat@users.noreply.github.com>
Date: Thu, 8 May 2025 17:46:40 +0200
Subject: [PATCH] fix: improve bookmarks

my computer broke so this commit is probably of a below average quality,
since i'm just backing stuff up.
---
 src/player.rs          | 13 ++++++-------
 src/tracks/bookmark.rs | 30 +++++++++++++++++++++++-------
 2 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/src/player.rs b/src/player.rs
index 0ebf4ba..c099dc1 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -299,7 +299,7 @@ impl Player {
         // only want to autoplay if there hasn't been any manual intervention.
         //
         // In other words, this will be `true` after a new track has been fully
-        // loaded  and it'll be `false` if a track is still currently loading.
+        // loaded and it'll be `false` if a track is still currently loading.
         let mut new = false;
 
         loop {
@@ -326,6 +326,8 @@ impl Player {
 
             match msg {
                 Messages::Next | Messages::Init | Messages::TryAgain => {
+                    player.bookmarked.swap(false, Ordering::Relaxed);
+
                     // We manually skipped, so we shouldn't actually wait for the song
                     // to be over until we recieve the `NewSong` signal.
                     new = false;
@@ -394,15 +396,10 @@ impl Player {
                     continue;
                 }
                 Messages::Bookmark => {
-                    if player.bookmarked.load(Ordering::Relaxed) {
-                        continue;
-                    }
-
-                    player.bookmarked.swap(true, Ordering::Relaxed);
                     let current = player.current.load();
                     let current = current.as_ref().unwrap();
 
-                    bookmark::bookmark(
+                    let bookmarked = bookmark::bookmark(
                         current.full_path.clone(),
                         if current.custom_name {
                             Some(current.display_name.clone())
@@ -411,6 +408,8 @@ impl Player {
                         },
                     )
                     .await?;
+
+                    player.bookmarked.swap(bookmarked, Ordering::Relaxed);
                 }
                 Messages::Quit => break,
             }
diff --git a/src/tracks/bookmark.rs b/src/tracks/bookmark.rs
index a5964fb..d8d91cd 100644
--- a/src/tracks/bookmark.rs
+++ b/src/tracks/bookmark.rs
@@ -1,11 +1,13 @@
 use tokio::fs::{create_dir_all, OpenOptions};
-use tokio::io::AsyncWriteExt;
+use tokio::io::{AsyncReadExt, AsyncWriteExt};
 
 use crate::data_dir;
 
-pub async fn bookmark(path: String, custom: Option<String>) -> eyre::Result<()> {
-    let mut entry = format!("\n{path}");
-
+/// Bookmarks a given track with a full path and optional custom name.
+///
+/// Returns whether the track is now bookmarked, or not.
+pub async fn bookmark(path: String, custom: Option<String>) -> eyre::Result<bool> {
+    let mut entry = format!("{path}");
     if let Some(custom) = custom {
         entry.push('!');
         entry.push_str(&custom);
@@ -17,11 +19,25 @@ pub async fn bookmark(path: String, custom: Option<String>) -> eyre::Result<()>
     let mut file = OpenOptions::new()
         .create(true)
         .write(true)
-        .append(true)
+        .read(true)
+        .append(false)
         .open(data_dir.join("bookmarks.txt"))
         .await?;
 
-    file.write_all(entry.as_bytes()).await?;
+    let mut text = String::new();
+    file.read_to_string(&mut text).await?;
 
-    Ok(())
+    let mut lines: Vec<&str> = text.lines().collect();
+    let previous_len = lines.len();
+    lines.retain(|line| (*line != entry));
+    let contains = lines.len() != previous_len;
+
+    if !contains {
+        lines.push(&entry);
+    }
+
+    file.set_len(0).await?;
+    file.write_all(format!("\n{}\n", lines.join("\n")).as_bytes()).await?;
+
+    Ok(!contains)
 }