started moving tabs logic into vue components

This commit is contained in:
Roberto Tonino 2020-07-07 22:04:26 +02:00
parent 763d5d201a
commit 02cdae80ab
6 changed files with 255 additions and 244 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,94 +1,82 @@
<template> <template functional>
<div id="about_tab" class="main_tabcontent"> <div id="about_tab" class="main_tabcontent">
<h2 class="page_heading">About</h2> <h2 class="page_heading">About</h2>
<p> <p>
This app uses the <a href="https://deemix.app" target="_blank">deemix</a> library, you can use this This app uses the <a href="https://deemix.app" target="_blank">deemix</a> library, you can use this
library to make your own UI for deemix.</br> library to make your own UI for deemix.</br>
Here's the <a href="https://notabug.org/RemixDev/deemix" target="_blank">official repo</a> for the Here's the <a href="https://notabug.org/RemixDev/deemix" target="_blank">official repo</a> for the
library. library.
</p> </p>
<p> <p>
Thanks to rtonno, uhwot and lollilol for helping me with this project.<br> Thanks to rtonno, uhwot and lollilol for helping me with this project.<br>
Also thanks to BasCurtiz and <a href="http://linktr.ee/scarvimane" target="_blank">scarvimane</a> for Also thanks to BasCurtiz and <a href="http://linktr.ee/scarvimane" target="_blank">scarvimane</a> for
making the icon. making the icon.
</p> </p>
<p> <p>
Stay up to date with the updates by following the <a href="https://t.me/RemixDevNews" Stay up to date with the updates by following the <a href="https://t.me/RemixDevNews"
target="_blank">news channel</a> on Telegram. target="_blank">news channel</a> on Telegram.
</p> </p>
<br /> <br />
<h1>Bug Reports</h1> <h1>Bug Reports</h1>
<p> <p>
If you have questions or problems with the app, search for a solution in the If you have questions or problems with the app, search for a solution in the
<a href="https://www.reddit.com/r/deemix" target="_blank">subreddit</a> first and then, if you don't <a href="https://www.reddit.com/r/deemix" target="_blank">subreddit</a> first and then, if you don't
find anything find anything
you can make a post with your issue on the subreddit. you can make a post with your issue on the subreddit.
</p> </p>
<p> <p>
Before reporting a bug make sure you're running the latest version of the app and that the thing you Before reporting a bug make sure you're running the latest version of the app and that the thing you
want want
to report is actually a bug and not something that's wrong only on your end.<br /> to report is actually a bug and not something that's wrong only on your end.<br />
Make sure the bug is reproducible on another machines and also <b>DO NOT</b> report a bug if it's been Make sure the bug is reproducible on another machines and also <b>DO NOT</b> report a bug if it's been
already reported. already reported.
</p> </p>
<p> <p>
<b>DO NOT</b> open issues for asking questions, there is a subreddit for that. <b>DO NOT</b> open issues for asking questions, there is a subreddit for that.
</p> </p>
<br /> <br />
<h2>Donations</h2> <h2>Donations</h2>
<h3>You want to contribute to this project? You can do that <b>in different ways!</b></h3> <h3>You want to contribute to this project? You can do that <b>in different ways!</b></h3>
<p> <p>
If you're fluent in python you could try to make a new UI for the app using the base library, or fix If you're fluent in python you could try to make a new UI for the app using the base library, or fix
bugs in the library with a pull request on the <a href="https://notabug.org/RemixDev/deemix" bugs in the library with a pull request on the <a href="https://notabug.org/RemixDev/deemix"
target="_blank">repo</a>.<br> target="_blank">repo</a>.<br>
I accept features as well, but no complex things, as they can be implementend directly in the app and I accept features as well, but no complex things, as they can be implementend directly in the app and
not the library.</p> not the library.</p>
<p> <p>
If you're fluent in another programming language you could try to port deemix into other programming If you're fluent in another programming language you could try to port deemix into other programming
languages!<br> languages!<br>
You need help understanding the code? Just hit RemixDev up on Telegram or Reddit.</p> You need help understanding the code? Just hit RemixDev up on Telegram or Reddit.</p>
<p>If you know JavaScript, HTML or CSS you could contribute to the <a <p>If you know JavaScript, HTML or CSS you could contribute to the <a
href="https://notabug.org/RemixDev/deemix-webui" target="_blank">webui</a>.</p> href="https://notabug.org/RemixDev/deemix-webui" target="_blank">webui</a>.</p>
<p> <p>
If you find some bugs you can report them in the repo, just make sure your bug isn't something that If you find some bugs you can report them in the repo, just make sure your bug isn't something that
only only
affects you and it can be reproducible by other users as well.<br> affects you and it can be reproducible by other users as well.<br>
Duplicate bug reports will be closed, so keep an eye out on that.</p> Duplicate bug reports will be closed, so keep an eye out on that.</p>
<hr> <hr>
<h3>You want to contribute monetarily? You could make a donation!</h3> <h3>You want to contribute monetarily? You could make a donation!</h3>
<p> <p>
If you can donate you can do that with this links.<br> If you can donate you can do that with this links.<br>
You shoud remember that <b>this is a free project</b> and <b>you should support the artists you You shoud remember that <b>this is a free project</b> and <b>you should support the artists you
love</b> love</b>
before supporting the developers.<br> before supporting the developers.<br>
Don't feel obligated to donate, I appreciate you anyway!</p> Don't feel obligated to donate, I appreciate you anyway!</p>
<p> <p>
<b>PayPal:</b> <a href="https://paypal.me/RemixDev" target="_blank">PayPal.me/RemixDev</a><br> <b>PayPal:</b> <a href="https://paypal.me/RemixDev" target="_blank">PayPal.me/RemixDev</a><br>
<b>Bitcoin:</b> 1sdNymSJrMBWyHM4u2m9uco5nv6uV4Qs1<br> <b>Bitcoin:</b> 1sdNymSJrMBWyHM4u2m9uco5nv6uV4Qs1<br>
<b>Ethereum:</b> 0x1d2aa67e671485CD4062289772B662e0A6Ff976c <b>Ethereum:</b> 0x1d2aa67e671485CD4062289772B662e0A6Ff976c
</p> </p>
<br /> <br />
<h2>License</h2> <h2>License</h2>
<p> <p>
<a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank"> <a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">
<img alt="GNU General Public License" style="border-width:0" <img alt="GNU General Public License" style="border-width:0"
src="https://www.gnu.org/graphics/gplv3-127x51.png" /> src="https://www.gnu.org/graphics/gplv3-127x51.png" />
</a><br /> </a><br />
This work is licensed under a <a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.en.html" This work is licensed under a <a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.en.html"
target="_blank">GNU General Public License 3.0</a>. target="_blank">GNU General Public License 3.0</a>.
</p> </p>
</div> </div>
</template> </template>
<script>
export default {
name: 'the-about-tab',
// Without this empty data rollup watcher throws an error
data() {
return {}
}
}
</script>
<style>
</style>

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="favorites_tab" class="main_tabcontent"> <div id="favorites_tab" class="main_tabcontent" @click="handleFavoritesTabClick">
<h2 class="page_heading"> <h2 class="page_heading">
Favorites Favorites
<div <div
@ -183,7 +183,7 @@
<script> <script>
import { socket } from '@/js/socket.js' import { socket } from '@/js/socket.js'
import { showView } from '@/js/tabs.js' import { showView, changeTab } from '@/js/tabs.js'
import Downloads from '@/js/downloads.js' import Downloads from '@/js/downloads.js'
import TrackPreview from '@/js/track-preview.js' import TrackPreview from '@/js/track-preview.js'
import Utils from '@/js/utils.js' import Utils from '@/js/utils.js'
@ -209,6 +209,36 @@ export default {
previewMouseEnter: TrackPreview.previewMouseEnter, previewMouseEnter: TrackPreview.previewMouseEnter,
previewMouseLeave: TrackPreview.previewMouseLeave, previewMouseLeave: TrackPreview.previewMouseLeave,
convertDuration: Utils.convertDuration, convertDuration: Utils.convertDuration,
handleFavoritesTabClick(event) {
const {
target,
target: { id }
} = event
let selectedTab = null
console.log(id)
switch (id) {
case 'favorites_playlist_tab':
selectedTab = 'playlist_favorites'
break
case 'favorites_album_tab':
selectedTab = 'album_favorites'
break
case 'favorites_artist_tab':
selectedTab = 'artist_favorites'
break
case 'favorites_track_tab':
selectedTab = 'track_favorites'
break
default:
break
}
if (!selectedTab) return
changeTab(target, 'favorites', selectedTab)
},
addToQueue(e) { addToQueue(e) {
e.stopPropagation() e.stopPropagation()
Downloads.sendAddToQueue(e.currentTarget.dataset.link) Downloads.sendAddToQueue(e.currentTarget.dataset.link)

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="search_tab" class="main_tabcontent"> <div id="search_tab" class="main_tabcontent" @click="handleSearchTabClick">
<div :class="{ hide: results.query != '' }"> <div :class="{ hide: results.query != '' }">
<h2>Start searching!</h2> <h2>Start searching!</h2>
<p> <p>
@ -443,6 +443,8 @@ import Downloads from '@/js/downloads.js'
import TrackPreview from '@/js/track-preview.js' import TrackPreview from '@/js/track-preview.js'
import Utils from '@/js/utils.js' import Utils from '@/js/utils.js'
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue' import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
import { changeTab } from '@/js/tabs.js'
import EventBus from '@/js/EventBus.js' import EventBus from '@/js/EventBus.js'
export default { export default {
@ -516,6 +518,38 @@ export default {
playPausePreview: TrackPreview.playPausePreview, playPausePreview: TrackPreview.playPausePreview,
previewMouseEnter: TrackPreview.previewMouseEnter, previewMouseEnter: TrackPreview.previewMouseEnter,
previewMouseLeave: TrackPreview.previewMouseLeave, previewMouseLeave: TrackPreview.previewMouseLeave,
handleSearchTabClick(event) {
const {
target,
target: { id }
} = event
let selectedTab = null
switch (id) {
case 'search_all_tab':
selectedTab = 'main_search'
break
case 'search_track_tab':
selectedTab = 'track_search'
break
case 'search_album_tab':
selectedTab = 'album_search'
break
case 'search_artist_tab':
selectedTab = 'artist_search'
break
case 'search_playlist_tab':
selectedTab = 'playlist_search'
break
default:
break
}
if (!selectedTab) return
changeTab(target, 'search', selectedTab)
},
handleClickTopResult(event) { handleClickTopResult(event) {
let topResultType = this.results.allTab.TOP_RESULT[0].type let topResultType = this.results.allTab.TOP_RESULT[0].type

View File

@ -1,5 +1,5 @@
<template> <template>
<aside id="sidebar" role="navigation"> <aside id="sidebar" role="navigation" @click="handleSidebarClick">
<span id="main_home_tablink" class="main_tablinks" role="link" aria-label="home"> <span id="main_home_tablink" class="main_tablinks" role="link" aria-label="home">
<i class="material-icons side_icon">home</i> <i class="material-icons side_icon">home</i>
<span class="main_tablinks_text">Home</span> <span class="main_tablinks_text">Home</span>
@ -63,7 +63,30 @@
</aside> </aside>
</template> </template>
<style scoped>
#network-status {
display: flex;
justify-content: center;
align-items: center;
position: relative;
margin-top: auto;
bottom: 0;
}
#network-status.online i.material-icons {
color: hsl(151, 100%, 31%);
}
#network-status.offline i.material-icons svg {
fill: red;
width: 1em;
height: 1em;
}
</style>
<script> <script>
import { changeTab } from '@/js/tabs.js'
export default { export default {
name: 'the-sidebar', name: 'the-sidebar',
data() { data() {
@ -107,28 +130,56 @@ export default {
document.documentElement.removeEventListener('transitionend', transitionHandler) document.documentElement.removeEventListener('transitionend', transitionHandler)
}) })
},
/**
* Handles click Event on the sidebar and changes tab
* according to clicked icon.
* Uses event delegation
* @param {Event} event
*/
handleSidebarClick(event) {
const { target } = event
const wantToChangeTab = target.matches('.main_tablinks') || target.parentElement.matches('.main_tablinks')
if (!wantToChangeTab) return
let sidebarEl = target.matches('.main_tablinks') ? target : target.parentElement
let targetID = sidebarEl.id
let selectedTab = null
switch (targetID) {
case 'main_search_tablink':
selectedTab = 'search_tab'
break
case 'main_home_tablink':
selectedTab = 'home_tab'
break
case 'main_charts_tablink':
selectedTab = 'charts_tab'
break
case 'main_favorites_tablink':
selectedTab = 'favorites_tab'
break
case 'main_analyzer_tablink':
selectedTab = 'analyzer_tab'
break
case 'main_settings_tablink':
selectedTab = 'settings_tab'
break
case 'main_about_tablink':
selectedTab = 'about_tab'
break
default:
break
}
if (!selectedTab) return
changeTab(sidebarEl, 'main', selectedTab)
} }
} }
} }
</script> </script>
<style scoped>
#network-status {
display: flex;
justify-content: center;
align-items: center;
position: relative;
margin-top: auto;
bottom: 0;
}
#network-status.online i.material-icons {
color: hsl(151, 100%, 31%);
}
#network-status.offline i.material-icons svg {
fill: red;
width: 1em;
height: 1em;
}
</style>

View File

@ -14,6 +14,7 @@ let currentStack = {}
// because it's used in components that are needed // because it's used in components that are needed
// in this file too // in this file too
export function showView(viewType, event) { export function showView(viewType, event) {
// console.error('SHOW VIEW')
const { const {
currentTarget: { currentTarget: {
dataset: { id } dataset: { id }
@ -47,144 +48,41 @@ export function updateSelected(newSelected) {
currentStack.selected = newSelected currentStack.selected = newSelected
} }
window.test = showErrors
function analyzeLink(link) { function analyzeLink(link) {
EventBus.$emit('linkAnalyzerTab:reset') EventBus.$emit('linkAnalyzerTab:reset')
socket.emit('analyzeLink', link) socket.emit('analyzeLink', link)
} }
function linkListeners() { export function changeTab(sidebarEl, section, tabName) {
document.getElementById('search_tab').addEventListener('click', handleSearchTabClick) // console.error('CHANGE TAB')
document.getElementById('favorites_tab').addEventListener('click', handleFavoritesTabClick) // console.log(Array.from(arguments))
document.getElementById('sidebar').addEventListener('click', handleSidebarClick)
const backButtons = Array.from(document.getElementsByClassName('back-button'))
backButtons.forEach(button => {
button.addEventListener('click', backTab)
})
}
/**
* Handles click Event on the sidebar and changes tab
* according to clicked icon.
* Uses event delegation
* @param {Event} event
*/
function handleSidebarClick(event) {
const { target } = event
const wantToChangeTab = target.matches('.main_tablinks') || target.parentElement.matches('.main_tablinks')
if (!wantToChangeTab) return
let sidebarEl = target.matches('.main_tablinks') ? target : target.parentElement
let targetID = sidebarEl.id
switch (targetID) {
case 'main_search_tablink':
changeTab(sidebarEl, 'main', 'search_tab')
break
case 'main_home_tablink':
changeTab(sidebarEl, 'main', 'home_tab')
break
case 'main_charts_tablink':
changeTab(sidebarEl, 'main', 'charts_tab')
break
case 'main_favorites_tablink':
changeTab(sidebarEl, 'main', 'favorites_tab')
break
case 'main_analyzer_tablink':
changeTab(sidebarEl, 'main', 'analyzer_tab')
break
case 'main_settings_tablink':
changeTab(sidebarEl, 'main', 'settings_tab')
break
case 'main_about_tablink':
changeTab(sidebarEl, 'main', 'about_tab')
break
default:
break
}
}
function handleSearchTabClick(event) {
const {
target,
target: { id }
} = event
switch (id) {
case 'search_all_tab':
changeTab(target, 'search', 'main_search')
break
case 'search_track_tab':
changeTab(target, 'search', 'track_search')
break
case 'search_album_tab':
changeTab(target, 'search', 'album_search')
break
case 'search_artist_tab':
changeTab(target, 'search', 'artist_search')
break
case 'search_playlist_tab':
changeTab(target, 'search', 'playlist_search')
break
default:
break
}
}
function handleFavoritesTabClick(event) {
const {
target,
target: { id }
} = event
switch (id) {
case 'favorites_playlist_tab':
changeTab(target, 'favorites', 'playlist_favorites')
break
case 'favorites_album_tab':
changeTab(target, 'favorites', 'album_favorites')
break
case 'favorites_artist_tab':
changeTab(target, 'favorites', 'artist_favorites')
break
case 'favorites_track_tab':
changeTab(target, 'favorites', 'track_favorites')
break
default:
break
}
}
function changeTab(sidebarEl, section, tabName) {
windows_stack = [] windows_stack = []
currentStack = {} currentStack = {}
var i, tabcontent, tablinks
tabcontent = document.getElementsByClassName(section + '_tabcontent') // * The visualized content of the tab
for (i = 0; i < tabcontent.length; i++) { // ! Can be more than one per tab, happens in MainSearch and Favorites tab
tabcontent[i].style.display = 'none' // ! because they have more tablinks (see below)
} const tabContent = document.getElementsByClassName(`${section}_tabcontent`)
tablinks = document.getElementsByClassName(section + '_tablinks')
// tablinks = document.getElementsByClassName('section-tabs__tab') for (let i = 0; i < tabContent.length; i++) {
for (i = 0; i < tablinks.length; i++) { tabContent[i].style.display = 'none'
tablinks[i].classList.remove('active')
} }
if (tabName == 'settings_tab' && main_selected != 'settings_tab') { // * Tabs inside the actual tab (like albums, tracks, playlists...)
const tabLinks = document.getElementsByClassName(`${section}_tablinks`)
for (let i = 0; i < tabLinks.length; i++) {
tabLinks[i].classList.remove('active')
}
if (tabName === 'settings_tab' && main_selected !== 'settings_tab') {
EventBus.$emit('settingsTab:revertSettings') EventBus.$emit('settingsTab:revertSettings')
EventBus.$emit('settingsTab:revertCredentials') EventBus.$emit('settingsTab:revertCredentials')
} }
document.getElementById(tabName).style.display = 'block' document.getElementById(tabName).style.display = 'block'
if ('main' === section) { if (section === 'main') {
main_selected = tabName main_selected = tabName
} else if ('search' === section) { } else if ('search' === section) {
search_selected = tabName search_selected = tabName
@ -194,14 +92,15 @@ function changeTab(sidebarEl, section, tabName) {
// Check if you need to load more content in the search tab // Check if you need to load more content in the search tab
if ( if (
main_selected == 'search_tab' && main_selected === 'search_tab' &&
['track_search', 'album_search', 'artist_search', 'playlist_search'].indexOf(search_selected) != -1 ['track_search', 'album_search', 'artist_search', 'playlist_search'].indexOf(search_selected) !== -1
) { ) {
EventBus.$emit('mainSearch:checkLoadMoreContent', search_selected) EventBus.$emit('mainSearch:checkLoadMoreContent', search_selected)
} }
} }
function showTab(type, id, back = false) { function showTab(type, id, back = false) {
// console.error('SHOW TAB')
if (windows_stack.length == 0) { if (windows_stack.length == 0) {
windows_stack.push({ tab: main_selected }) windows_stack.push({ tab: main_selected })
} else if (!back) { } else if (!back) {
@ -226,6 +125,7 @@ function showTab(type, id, back = false) {
} }
function backTab() { function backTab() {
// console.error('BACL TAB')
if (windows_stack.length == 1) { if (windows_stack.length == 1) {
document.getElementById(`main_${main_selected}link`).click() document.getElementById(`main_${main_selected}link`).click()
} else { } else {
@ -250,6 +150,14 @@ function backTab() {
TrackPreview.stopStackedTabsPreview() TrackPreview.stopStackedTabsPreview()
} }
function linkListeners() {
const backButtons = Array.from(document.getElementsByClassName('back-button'))
backButtons.forEach(button => {
button.addEventListener('click', backTab)
})
}
function init() { function init() {
// Open default tab // Open default tab
changeTab(document.getElementById('main_home_tablink'), 'main', 'home_tab') changeTab(document.getElementById('main_home_tablink'), 'main', 'home_tab')