lichess-org / lila

♞ lichess.org: the forever free, adless and open source chess server ♞
https://lichess.org
GNU Affero General Public License v3.0
14.82k stars 2.2k forks source link

Filter subscribed streamers in streamer list #12522

Open kraktus opened 1 year ago

kraktus commented 1 year ago

Either create a new section on the side of https://lichess.org/streamer or a toggle somewhere. The former is probably cleaner.

I subscribed to a streamer on lichess.org/streamer but would like to unsubscribe as I don't find the feature useful. I don't catch them live so they're not sorted to the top which would make it easy. Trying to find them by scrolling down, waiting for more to load, scrolling more has succeeded only in bogging the page down to a crawl as it grows.

source: https://lichess.org/forum/lichess-feedback/feature-request-make-it-easier-to-unsubscribe-from-a-streamer#5

ross39 commented 1 year ago

I would like to look into this. I presume there is a list of streamers the user has subscribed to kept somewhere in the code, most likely modules/streamer/streamer.scala? All that would need to be done then is to create a new section in the navbar of https://lichess.org/streamer and then display a list of streamers the user has subscribed to? I'm probably overly optimistic on the steps needed to implement this improvement but that's my understanding of it.

ross39 commented 1 year ago

It seems module/relation/SubscriptionRepo.scala writes the subscription to the mongodb database. There seems to be a scala method/function called filterSubscribed() that retrieves streamers the user has subscribed to? If so the improvement just involves displaying that query in a new page so the user can easily see which streamers they have subscribed to etc?

schlawg commented 1 year ago

Hey Ross, you're on the right track there. But you'll need a new method in SubscriptionRepo, something like:

  def subscribedByUser(userId: UserId): Fu[List[UserId]] =
    coll.distinctEasy[String, List]("s", $doc("u" -> userId)).map(ids => UserId from ids)

You could also write that query to run on the _id index, but the above's easier to look at and thibault can make that change if it's needed.

ross39 commented 1 year ago

thanks for the information. For testing locally I presume the best way to go about it is to make a few dummy streamers and then subscribe to them and see if the new method successfully retrieves all the streamers that userID has subscribed to?

schlawg commented 1 year ago

Sure, but you might want to refresh the page after making each subscription change before checking results.

ross39 commented 1 year ago

Hi, Just wondering about this code.

def subscribedByUser(userId: UserId): Fu[List[UserId]] = coll.distinctEasy[String, List]("s", $doc("u" -> userId)).map(ids => UserId from ids)

I understand you're just pointing me in the right direction and there is no expectation for the code to completely work and its up to me to verify and fix. However this code fails to compile as it expects a concurrent.Future[Boolean]. Being new to scala with some java experience I was a bit confused at first and I did some digging around in the code.

I rewrote the following code, well really changed one bit, to the following

def subscribedByUser(userId: UserId): Fu[List[UserId]] = coll.distinctEasy[String, List]("_id", $doc("u" -> userId)).map(ids => UserId from ids)

Essentially its the exact same but "s" has been changed to "_id" and this seems to compile just fine. I have yet to fully verify the code works, doing that right now. But does the change I made make sense to you? To me it makes sense as we are retrieving the _id from the doc, I could be completely wrong though. I am continuing to dig through the code as I want to verify this actually works and learn more about how mongodb stuff is done in the lichess code.

schlawg commented 1 year ago

You changed a string but the method signature is the same. This means there was another reason it wasn't compiling before. "_id" is different than "s". If you use "_id", you'll need to parse it to get the streamer id

ross39 commented 1 year ago

yeah you're right. I reverted back to "u" and it seemed to compile just fine so not sure what the issue was. Anyways I have added the new page to the navbar along with the necessary addition to streamer.xml,

<string name="subscribedStreamers">Subscribed streamers</string>

The new page is successfully showing in the navbar. However I cannot seem to figure out how exactly to make the page load properly? For example in the navbar there is a link to /about which links to this page https://lichess.org/about. Specifically the navbar i am referring to is the navbar on https://lichess.org/streamer. However when I click the link on lichess.dev I get a page not found error and I cannot seem to find the code for this page in the repo? I will probably figure this out myself eventually but any pointers would be appreciated.

kraktus commented 1 year ago

Hey, don’t worry about the about page, it’s hosted on a service (prismic.io) that allow dynamic edits, that’s why it’s not in the code.

ross39 commented 1 year ago

Just wondering what the best approach to take is for displaying the filtered streamers is. In controllers/streamer.scala I have created the following method.

def subscribedByUser = Auth { implicit ctx => me => env.relation.subs.subscribedByUser(me.id) map { streamers => Ok(html.streamer.show(streamers)) } }

Which calls the def subscribedByUser(userId: UserId): Fu[List[UserId]] = coll.distinctEasy[String, List]("s", $doc("u" -> userId)).map(ids => UserId from ids) in SubscriptionRepo.scala.

Now clearly this won't work as views/streamer/show.scala is expecting the following arguments

def apply( s: lila.streamer.Streamer.WithUserAndStream, activities: Vector[lila.activity.ActivityView] )

Is it best to create a new method in streamer/show.scala that will take in the list[UserID] or is there a way to still use the original def apply in streamer/show.scala? Hopefully what I have asked makes sense. If not I am happy to clarify any points.

ross39 commented 1 year ago

Hi, Still kinda stuck on this although I have only looked at it for a few hours since my last comment. I think the question really is how do I reuse the show streamer code(views/streamer/show) to display a list of streamers that the user has subscribed to? I'd rather not add a bunch of unnecessary code to views/streamer/show.scala if its possible to reuse the same code. I am actively looking into this but if anyone can point me in the right direction that would be great.