diff --git a/Web/Presenters/templates/Audio/List.xml b/Web/Presenters/templates/Audio/List.xml
index 189cd4a0..f7add614 100644
--- a/Web/Presenters/templates/Audio/List.xml
+++ b/Web/Presenters/templates/Audio/List.xml
@@ -41,7 +41,7 @@
     <input n:if="$mode == 'popular'" type="hidden" name="bigplayer_context" data-type="popular_audios" data-entity="0" data-page="1">
     
     <div style="width: 100%;display: flex;margin-bottom: -10px;">
-        <div style="width: 74%;" n:if="$mode != 'playlists'">
+        <div style="width: 74%;" class="audiosContainer" n:if="$mode != 'playlists'">
             <div style="padding: 8px;">
                 <div n:if="$audiosCount <= 0">
                     {include "../components/nothing.xml"}
diff --git a/Web/Presenters/templates/Audio/player.xml b/Web/Presenters/templates/Audio/player.xml
index 764e8dd2..558a1aea 100644
--- a/Web/Presenters/templates/Audio/player.xml
+++ b/Web/Presenters/templates/Audio/player.xml
@@ -4,7 +4,7 @@
 {php $id = $audio->getId() . rand(0, 1000)}
 {php $isWithdrawn = $audio->isWithdrawn()}
 {php $editable = $audio->canBeModifiedBy($thisUser)}
-<div id="audioEmbed-{$id}" data-realid="{$audio->getId()}" data-genre="{$audio->getGenre()}" class="audioEmbed {if !$audio->isAvailable()}lagged{/if} {if $isWithdrawn}withdrawn{/if}" onmouseenter="!this.classList.contains('inited') ? initPlayer({$id}, {$audio->getKeys()}, {$audio->getURL()}, {$audio->getLength()}) : console.log('Player already inited.')">
+<div id="audioEmbed-{$id}" data-realid="{$audio->getId()}" data-genre="{$audio->getGenre()}" class="audioEmbed {if !$audio->isAvailable()}lagged{/if} {if $isWithdrawn}withdrawn{/if}" onmouseenter="!this.classList.contains('inited') ? initPlayer({$id}, {$audio->getKeys()}, {$audio->getURL()}, {$audio->getLength()}) : void(0)">
     <audio class="audio" />
 
     <div id="miniplayer" class="audioEntry" style="min-height: 37px;">
diff --git a/Web/static/css/audios.css b/Web/static/css/audios.css
index 3abbd486..50f1864d 100644
--- a/Web/static/css/audios.css
+++ b/Web/static/css/audios.css
@@ -5,7 +5,7 @@
 }
 
 .musicIcon.pressed {
-    filter: brightness(59%);
+    filter: brightness(0%);
 }
 
 .bigPlayer {
@@ -229,7 +229,7 @@
     color: white !important;
 }
 
-.audioEntry.nowPlaying .buttons .musicIcon {
+.audioEntry.nowPlaying .buttons .musicIcon, .audioEntry.nowPlaying svg {
     filter: brightness(187%) opacity(72%);
 }
 
diff --git a/Web/static/img/play_buttons.gif b/Web/static/img/play_buttons.gif
index 35bc6bc3..c561bb89 100644
Binary files a/Web/static/img/play_buttons.gif and b/Web/static/img/play_buttons.gif differ
diff --git a/Web/static/js/al_music.js b/Web/static/js/al_music.js
index 15865fbb..797b77dc 100644
--- a/Web/static/js/al_music.js
+++ b/Web/static/js/al_music.js
@@ -4,6 +4,10 @@ function fmtTime(time) {
     return `${ mins}:${ secs}`;
 }
 
+function fastError(message) {
+    MessageBox(tr("error"), message, [tr("ok")], [Function.noop])
+}
+
 // нихуя я тут насрал
 class bigPlayer {
     contextObject = []
@@ -15,6 +19,9 @@ class bigPlayer {
         this.context = context
         this.context_id = context_id
         this.playerNode = document.querySelector(".bigPlayer")
+
+        this.playerNode.classList.add("lagged")
+
         this.performer = this.playerNode.querySelector(".trackInfo b")
         this.name = this.playerNode.querySelector(".trackInfo span")
         this.time = this.playerNode.querySelector(".trackInfo .time")
@@ -34,6 +41,7 @@ class bigPlayer {
                 afterResponse: [
                     async (_request, _options, response) => {
                         this.contextObject = await response.json()
+                        this.playerNode.classList.remove("lagged")
                         console.info("Context is successfully loaded")
                     }
                 ]
@@ -56,6 +64,7 @@ class bigPlayer {
 
             if (ps <= 100)
                 this.playerNode.querySelector(".selectableTrack .slider").style.left = `${ ps}%`;
+
         })
 
         u(this.player()).on("volumechange", (e) => {
@@ -187,8 +196,13 @@ class bigPlayer {
         document.querySelectorAll(".audioEntry.nowPlaying").forEach(el => el.classList.remove("nowPlaying"))
         let obj = this.contextObject["items"].find(item => item.id == id)
 
-        this.name.innerHTML = obj.name 
-        this.performer.innerHTML = obj.performer
+        if(obj == null) {
+            fastError("No audio in context")
+            return
+        }
+
+        this.name.innerHTML = escapeHtml(obj.name) 
+        this.performer.innerHTML = escapeHtml(obj.performer)
         this.time.innerHTML = fmtTime(obj.length)
         this.currentTrack = obj
 
@@ -201,7 +215,6 @@ class bigPlayer {
             this.previousTrack = null
         }
 
-        // todo поменьше копипастить код
         if(this.nextTrack == null && this.contextObject.page < this.contextObject.pagesCount
             || this.previousTrack == null && (this.contextObject.page > 1)) {
             let formdata = new FormData()
@@ -422,14 +435,14 @@ $(document).on("click", ".musicIcon.edit-icon", (e) => {
                 success: (response) => {
                     if(response.success) {
                         let perf = player.querySelector(".performer a")
-                        perf.innerHTML = response.new_info.performer
+                        perf.innerHTML = escapeHtml(response.new_info.performer)
                         perf.setAttribute("href", "/search?query=&type=audios&sort=id&only_performers=on&query="+response.new_info.performer)
                         
-                        e.currentTarget.setAttribute("data-performer", response.new_info.performer)
+                        e.currentTarget.setAttribute("data-performer", escapeHtml(response.new_info.performer))
                         let name = player.querySelector(".title")
                         name.innerHTML = escapeHtml(response.new_info.name)
 
-                        e.currentTarget.setAttribute("data-title", response.new_info.name)
+                        e.currentTarget.setAttribute("data-title", escapeHtml(response.new_info.name))
                         
                         if(player.querySelector(".lyrics") != null) {
                             player.querySelector(".lyrics").innerHTML = response.new_info.lyrics
@@ -575,4 +588,70 @@ $(document).on("click", "#bookmarkPlaylist", (e) => {
 
 $(document).on("click", "#unbookmarkPlaylist", (e) => {
     
-})
\ No newline at end of file
+})
+
+$(document).on("click", ".audiosContainer .paginator a", (e) => {
+    e.preventDefault()
+
+    e.currentTarget.parentNode.classList.add("lagged")
+
+    ky(e.currentTarget.href, {
+        hooks: {
+            afterResponse: [
+                async (_request, _options, response) => {
+                    let text = await response.text()
+                    let domparse = (new DOMParser()).parseFromString(text, "text/html")
+
+                    document.querySelector(".audiosContainer").innerHTML = domparse.querySelector(".audiosContainer").innerHTML
+                    history.pushState(null, null, e.currentTarget.href)
+
+                    let playingId = window.player.currentTrack["id"] ?? 0
+                    let maybePlayer = document.querySelector(`.audioEmbed[data-realid='${playingId}'] .audioEntry`)
+                    console.log(playingId)
+
+                    if(maybePlayer != null) {
+                        maybePlayer.classList.add("nowPlaying")
+                    }
+                }
+            ]
+        }
+    })
+
+    let url = new URL(location.href)
+    let lesser = Number(url.searchParams.get("p")) < window.player.contextObject["page"]
+
+    let formdata = new FormData()
+    formdata.append("context", window.player.context)
+    formdata.append("context_entity", window.player.context_id)
+    formdata.append("hash", u("meta[name=csrf]").attr("value"))
+    formdata.append("page", Number(url.searchParams.get("p")) + (lesser ? -1 : 1))
+
+    ky.post("/audios/context", {
+        hooks: {
+            afterResponse: [
+                async (_request, _options, response) => {
+                    let newArr = await response.json()
+                    let indexOfCurrentTrack = window.player.contextObject["items"].indexOf(window.player.currentTrack) ?? 0
+
+                    if(lesser) {
+                        window.player.contextObject["items"] = newArr["items"].concat(window.player.contextObject["items"])
+                    } else {
+                        window.player.contextObject["items"] = window.player.contextObject["items"].concat(newArr["items"])
+                    }
+
+                    window.player.contextObject["page"] = newArr["page"]
+                    
+                    if(lesser) {
+                        window.player.previousTrack = window.player.contextObject["items"].at(window.player.contextObject["items"].indexOf(obj) - 1).id
+                     } else {
+                        window.player.nextTrack = window.player.contextObject["items"].at(indexOfCurrentTrack + 1) != null ? window.player.contextObject["items"].at(indexOfCurrentTrack + 1).id : null
+                    }
+                    
+                    window.player.updateButtons()
+                    console.info("Context is successfully loaded")
+                }
+            ]
+        }, 
+        body: formdata
+    })
+})