diff --git a/app/controllers/Video.scala b/app/controllers/Video.scala index c3cbe721a0..db2282429d 100644 --- a/app/controllers/Video.scala +++ b/app/controllers/Video.scala @@ -16,26 +16,18 @@ object Video extends LilaController { private def WithUserControl[A](f: UserControl => Fu[A])(implicit ctx: Context): Fu[A] = { val reqTags = get("tags") ?? (_.split(',').toList.map(_.trim.toLowerCase)) - env.api.tag.pathsAnd(30, reqTags) map { tags => - UserControl( - filter = Filter(reqTags), - tags = tags) + env.api.tag.paths(reqTags) map { tags => + UserControl(filter = Filter(reqTags), tags = tags) } flatMap f } - private def renderIndex(control: UserControl)(implicit ctx: Context) = - env.api.video.byTags(control.filter.tags, getInt("page") | 1) zip - env.api.video.count.apply map { - case (videos, count) => - Ok(html.video.index(videos, count, control)) - } - def index = Open { implicit ctx => WithUserControl { control => - val filter = control.filter.copy( - tags = get("tags") ?? (_.split(',').toList.map(_.trim.toLowerCase)) - ) - renderIndex(control.copy(filter = filter)) + env.api.video.byTags(control.filter.tags, getInt("page") | 1) zip + env.api.video.count.apply map { + case (videos, count) => + Ok(html.video.index(videos, count, control)) + } } } diff --git a/app/views/video/layout.scala.html b/app/views/video/layout.scala.html index 14ac9b378d..1b79b9713c 100644 --- a/app/views/video/layout.scala.html +++ b/app/views/video/layout.scala.html @@ -13,6 +13,11 @@ } } + @if(control.filter.tags.nonEmpty) { +
+ Clear search +
+ } } diff --git a/modules/video/src/main/Env.scala b/modules/video/src/main/Env.scala index a37e65bf87..7193d05967 100644 --- a/modules/video/src/main/Env.scala +++ b/modules/video/src/main/Env.scala @@ -47,10 +47,6 @@ final class Env( youtube.updateAll logFailure "video youtube" } - scheduler.once(15 seconds) { - sheet.fetchAll >> youtube.updateAll logFailure "video boot" - } - private[video] lazy val videoColl = db(CollectionVideo) private[video] lazy val viewColl = db(CollectionView) private[video] lazy val filterColl = db(CollectionFilter) diff --git a/modules/video/src/main/VideoApi.scala b/modules/video/src/main/VideoApi.scala index f4a550a3a7..a92b67e44e 100644 --- a/modules/video/src/main/VideoApi.scala +++ b/modules/video/src/main/VideoApi.scala @@ -4,11 +4,11 @@ import org.joda.time.DateTime import reactivemongo.bson._ import reactivemongo.core.commands._ import scala.concurrent.duration._ -import spray.caching.{ LruCache, Cache } import lila.common.paginator._ import lila.db.paginator.BSONAdapter import lila.db.Types.Coll +import lila.memo.AsyncCache import lila.user.{ User, UserRepo } private[video] final class VideoApi( @@ -104,13 +104,14 @@ private[video] final class VideoApi( } object count { - private val cache: Cache[Int] = LruCache(timeToLive = 1.day) - def clearCache = fuccess(cache.clear) + private val cache = AsyncCache.single( + f = videoColl.db command Count(videoColl.name, none), + timeToLive = 1.day) - def apply: Fu[Int] = cache(true) { - videoColl.db command Count(videoColl.name, none) - } + def clearCache = cache.clear + + def apply: Fu[Int] = cache apply true } } @@ -133,54 +134,58 @@ private[video] final class VideoApi( object tag { - private val nbCache: Cache[List[TagNb]] = LruCache(timeToLive = 1.day) + def paths(filterTags: List[Tag]): Fu[List[TagNb]] = pathsCache(filterTags.sorted) - def clearCache = fuccess { - nbCache.clear - } + def clearCache = pathsCache.clear >> popularCache.clear - def pathsAnd(max: Int, forced: List[Tag]): Fu[List[TagNb]] = - popular zip paths(forced) map { - case (all, paths) => - val tags = all take max map { t => - paths find (_._id == t._id) getOrElse TagNb(t._id, 0) + private val max = 25 + + private val pathsCache = AsyncCache[List[Tag], List[TagNb]]( + f = filterTags => { + val allPaths = + if (filterTags.isEmpty) popularCache(true) + else { + val command = Aggregate(videoColl.name, Seq( + Match(BSONDocument("tags" -> BSONDocument("$all" -> filterTags))), + Project("tags" -> BSONBoolean(true)), + Unwind("tags"), + GroupField("tags")("nb" -> SumValue(1)) + )) + videoColl.db.command(command) map { + _.toList.flatMap(_.asOpt[TagNb]) + } } - val missing = forced filterNot { t => - tags exists (_.tag == t) - } - tags.take(max - missing.size) ::: missing.flatMap { t => - all find (_.tag == t) - } - } + popularCache(true) zip allPaths map { + case (all, paths) => + val tags = all map { t => + paths find (_._id == t._id) getOrElse TagNb(t._id, 0) + } filterNot (_.empty) take max + val missing = filterTags filterNot { t => + tags exists (_.tag == t) + } + val list = tags.take(max - missing.size) ::: missing.flatMap { t => + all find (_.tag == t) + } + list.sortBy { t => + if (filterTags contains t.tag) Int.MinValue + else -t.nb + } + } + }, + timeToLive = 1.day) - def popular: Fu[List[TagNb]] = nbCache("") { - import reactivemongo.core.commands._ - val command = Aggregate(videoColl.name, Seq( - Project("tags" -> BSONBoolean(true)), - Unwind("tags"), - GroupField("tags")("nb" -> SumValue(1)), - Sort(Seq(Descending("nb"))) - )) - videoColl.db.command(command) map { - _.toList.flatMap(_.asOpt[TagNb]) - } - } - - def paths(tags: List[Tag]): Fu[List[TagNb]] = - if (tags.isEmpty) popular - else nbCache(tags.sorted.mkString(",")) { - import reactivemongo.core.commands._ + private val popularCache = AsyncCache.single[List[TagNb]]( + f = { val command = Aggregate(videoColl.name, Seq( - Match(BSONDocument("tags" -> BSONDocument("$all" -> tags))), Project("tags" -> BSONBoolean(true)), Unwind("tags"), - // Match(BSONDocument("tags" -> BSONDocument("$nin" -> tags))), GroupField("tags")("nb" -> SumValue(1)), Sort(Seq(Descending("nb"))) )) videoColl.db.command(command) map { _.toList.flatMap(_.asOpt[TagNb]) } - } + }, + timeToLive = 1.day) } } diff --git a/modules/video/src/main/control.scala b/modules/video/src/main/control.scala index b53ca92832..f233dd3827 100644 --- a/modules/video/src/main/control.scala +++ b/modules/video/src/main/control.scala @@ -5,6 +5,8 @@ import org.joda.time.DateTime case class TagNb(_id: Tag, nb: Int) { def tag = _id + + def empty = nb == 0 } case class Filter(tags: List[String]) { diff --git a/public/stylesheets/video.css b/public/stylesheets/video.css index 0b032c4289..e4fa7f607b 100644 --- a/public/stylesheets/video.css +++ b/public/stylesheets/video.css @@ -147,6 +147,10 @@ opacity: 0.5; cursor: default; } +#video_side .under_tags { + margin-top: 2em; + text-align: center; +} #video .not_found { margin-top: 200px;