Merge pull request 'update' (#2) from RemixDev/deemix-webui:main into main
Reviewed-on: https://codeberg.org/wolfwork/deemix-webui/pulls/2
This commit is contained in:
commit
bf9706c2c1
@ -1,19 +0,0 @@
|
||||
{
|
||||
"css": {
|
||||
"allowed_file_extensions": [
|
||||
"css",
|
||||
"scss",
|
||||
"sass",
|
||||
"less"
|
||||
],
|
||||
"end_with_newline": true,
|
||||
"indent_char": " ",
|
||||
"indent_size": 2,
|
||||
"indent_with_tabs": true,
|
||||
"newline_between_rules": true,
|
||||
"selector_separator": " ",
|
||||
"selector_separator_newline": false,
|
||||
"preserve_newlines": true,
|
||||
"max_preserve_newlines": 3
|
||||
}
|
||||
}
|
@ -11,6 +11,15 @@ You can find more informations about deemix at https://deemix.app/
|
||||
- [deemix-pyweb](https://codeberg.org/RemixDev/deemix-pyweb)
|
||||
- [deemix-tools](https://codeberg.org/RemixDev/deemix-tools)
|
||||
|
||||
# "Hidden" features
|
||||
|
||||
- `CTRL+SHIFT+Backspace` deletes all the search bar content
|
||||
- `CTRL+F` focuses the search bar
|
||||
- `CTRL+B` toggles the download bar
|
||||
- `ALT+Left` goes back to the previous page, if present (like would happen in the browser)
|
||||
- `ALT+Right` goes forward to the next page, if present (like would happen in the browser)
|
||||
- Custom context menu: on certain elements, like download buttons or album covers, when opening the context menu, a custom one with more options will appear instead of the default one
|
||||
|
||||
# License
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -796,6 +796,11 @@
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"flag-icon-css": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/flag-icon-css/-/flag-icon-css-3.5.0.tgz",
|
||||
"integrity": "sha512-pgJnJLrtb0tcDgU1fzGaQXmR8h++nXvILJ+r5SmOXaaL/2pocunQo2a8TAXhjQnBpRLPtZ1KCz/TYpqeNuE2ew=="
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
|
@ -19,6 +19,7 @@
|
||||
"build": "npm-run-all --sequential clean build:js build:styles"
|
||||
},
|
||||
"dependencies": {
|
||||
"flag-icon-css": "^3.5.0",
|
||||
"lodash-es": "^4.17.15",
|
||||
"svg-country-flags": "^1.2.7",
|
||||
"toastify-js": "^1.8.0",
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -31,10 +31,6 @@ export default {
|
||||
find: '@',
|
||||
replacement: __dirname + '/src'
|
||||
},
|
||||
{
|
||||
find: '@js',
|
||||
replacement: __dirname + '/src/js'
|
||||
},
|
||||
{
|
||||
find: '@components',
|
||||
replacement: __dirname + '/src/components'
|
||||
|
@ -5,9 +5,9 @@
|
||||
<div class="app-container">
|
||||
<div class="content-container">
|
||||
<TheSearchBar />
|
||||
<TheMiddleSection />
|
||||
<TheContent />
|
||||
</div>
|
||||
<TheDownloadTab class="downlaods" />
|
||||
<TheDownloadBar />
|
||||
</div>
|
||||
|
||||
<BaseLoadingPlaceholder id="start_app_placeholder" text="Connecting to the server..." />
|
||||
@ -30,32 +30,30 @@
|
||||
flex-direction: column;
|
||||
margin-left: 48px;
|
||||
}
|
||||
|
||||
.downlaods {
|
||||
flex-basis: 32px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import TheDownloadBar from '@components/downloads/TheDownloadBar.vue'
|
||||
|
||||
import BaseLoadingPlaceholder from '@components/globals/BaseLoadingPlaceholder.vue'
|
||||
import TheContextMenu from '@components/globals/TheContextMenu.vue'
|
||||
import TheTrackPreview from '@components/globals/TheTrackPreview.vue'
|
||||
import TheQualityModal from '@components/globals/TheQualityModal.vue'
|
||||
|
||||
import TheSidebar from '@components/TheSidebar.vue'
|
||||
import TheMiddleSection from '@components/TheMiddleSection.vue'
|
||||
import TheTrackPreview from '@components/TheTrackPreview.vue'
|
||||
import TheQualityModal from '@components/TheQualityModal.vue'
|
||||
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
|
||||
import TheContextMenu from '@components/TheContextMenu.vue'
|
||||
import TheDownloadTab from '@components/TheDownloadTab.vue'
|
||||
import TheSearchBar from '@components/TheSearchBar.vue'
|
||||
import TheContent from '@components/TheContent.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TheSidebar,
|
||||
TheSearchBar,
|
||||
TheMiddleSection,
|
||||
TheDownloadTab,
|
||||
TheDownloadBar,
|
||||
TheTrackPreview,
|
||||
TheQualityModal,
|
||||
BaseLoadingPlaceholder,
|
||||
TheContextMenu
|
||||
TheContextMenu,
|
||||
TheContent
|
||||
}
|
||||
}
|
||||
</script>
|
66
src/app.js
66
src/app.js
@ -5,27 +5,18 @@ window.vol = {
|
||||
preview_max_volume: 100
|
||||
}
|
||||
|
||||
import App from '@components/App.vue'
|
||||
import App from '@/App.vue'
|
||||
import i18n from '@/plugins/i18n'
|
||||
import router from '@/router'
|
||||
import store from '@/store'
|
||||
|
||||
import { socket } from '@/utils/socket'
|
||||
import { toast } from '@/utils/toasts'
|
||||
import { init as initTabs } from '@js/tabs.js'
|
||||
|
||||
import { isValidURL } from '@/utils/utils'
|
||||
import Downloads from '@/utils/downloads'
|
||||
import EventBus from '@/utils/EventBus.js'
|
||||
import { sendAddToQueue } from '@/utils/downloads'
|
||||
|
||||
/* ===== App initialization ===== */
|
||||
|
||||
function startApp() {
|
||||
mountApp()
|
||||
initTabs()
|
||||
}
|
||||
|
||||
function mountApp() {
|
||||
new Vue({
|
||||
store,
|
||||
router,
|
||||
@ -36,6 +27,7 @@ function mountApp() {
|
||||
|
||||
function initClient() {
|
||||
store.dispatch('setClientMode', true)
|
||||
setClientModeKeyBindings()
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', startApp)
|
||||
@ -44,24 +36,40 @@ window.addEventListener('pywebviewready', initClient)
|
||||
/* ===== Global shortcuts ===== */
|
||||
|
||||
document.addEventListener('paste', pasteEvent => {
|
||||
let pasteText = pasteEvent.clipboardData.getData('Text')
|
||||
if (pasteEvent.target.localName === 'input') return
|
||||
|
||||
if (pasteEvent.target.localName != 'input') {
|
||||
if (isValidURL(pasteText)) {
|
||||
if (window.main_selected === 'analyzer_tab') {
|
||||
EventBus.$emit('linkAnalyzerTab:reset')
|
||||
socket.emit('analyzeLink', pasteText)
|
||||
} else {
|
||||
Downloads.sendAddToQueue(pasteText)
|
||||
}
|
||||
let pastedText = pasteEvent.clipboardData.getData('Text')
|
||||
|
||||
if (isValidURL(pastedText)) {
|
||||
if (router.currentRoute.name === 'Link Analyzer') {
|
||||
socket.emit('analyzeLink', pastedText)
|
||||
} else {
|
||||
let searchbar = document.querySelector('#searchbar')
|
||||
searchbar.select()
|
||||
searchbar.setSelectionRange(0, 99999)
|
||||
sendAddToQueue(pastedText)
|
||||
}
|
||||
} else {
|
||||
let searchbar = document.querySelector('#searchbar')
|
||||
searchbar.select()
|
||||
searchbar.setSelectionRange(0, 99999)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Sets up key bindings that already work in the browser (server mode)
|
||||
*/
|
||||
function setClientModeKeyBindings() {
|
||||
document.addEventListener('keyup', keyEvent => {
|
||||
// ALT + left
|
||||
if (keyEvent.altKey && keyEvent.key === 'ArrowLeft') {
|
||||
router.back()
|
||||
}
|
||||
|
||||
// ALT + right
|
||||
if (keyEvent.altKey && keyEvent.key === 'ArrowRight') {
|
||||
router.forward()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* ===== Socketio listeners ===== */
|
||||
|
||||
// Debug messages for socketio
|
||||
@ -113,11 +121,13 @@ socket.on('logged_in', function(data) {
|
||||
break
|
||||
case -1:
|
||||
toast(i18n.t('toasts.deezerNotAvailable'), 'close', true, 'login-toast')
|
||||
$('#open_login_prompt').show()
|
||||
document.getElementById('logged_in_info').classList.add('hide')
|
||||
$('#settings_username').text('Not Logged')
|
||||
$('#settings_picture').attr('src', `https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`)
|
||||
document.getElementById('home_not_logged_in').classList.remove('hide')
|
||||
return
|
||||
// TODO
|
||||
// $('#open_login_prompt').show()
|
||||
// document.getElementById('logged_in_info').classList.add('hide')
|
||||
// $('#settings_username').text('Not Logged')
|
||||
// $('#settings_picture').attr('src', `https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`)
|
||||
// document.getElementById('home_not_logged_in').classList.remove('hide')
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<section id="content" @scroll="$route.name === 'Search' ? handleContentScroll($event) : null" ref="content">
|
||||
<main
|
||||
id="content"
|
||||
@scroll="$route.name === 'Search' ? handleContentScroll($event) : null"
|
||||
ref="content"
|
||||
aria-label="main content"
|
||||
>
|
||||
<div id="container">
|
||||
<BaseLoadingPlaceholder id="search_placeholder" text="Searching..." :hidden="!loading" />
|
||||
|
||||
@ -21,7 +26,7 @@
|
||||
exclude=""
|
||||
></router-view>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@ -31,8 +36,9 @@
|
||||
width: var(--container-width);
|
||||
}
|
||||
|
||||
#content {
|
||||
main {
|
||||
background-color: var(--main-background);
|
||||
padding-right: 5px;
|
||||
width: 100%;
|
||||
height: calc(100vh - 93px);
|
||||
overflow-y: scroll;
|
||||
@ -57,8 +63,7 @@
|
||||
|
||||
<script>
|
||||
import { debounce } from '@/utils/utils'
|
||||
import EventBus from '@/utils/EventBus.js'
|
||||
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
|
||||
import BaseLoadingPlaceholder from '@components/globals/BaseLoadingPlaceholder.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -72,6 +77,11 @@ export default {
|
||||
this.$root.$on('updateSearchLoadingState', loading => {
|
||||
this.loading = loading
|
||||
})
|
||||
|
||||
this.$router.beforeEach((to, from, next) => {
|
||||
this.$refs.content.scrollTo(0, 0)
|
||||
next()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleContentScroll: debounce(async function () {
|
||||
|
@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<main id="main_content">
|
||||
<TheContent />
|
||||
<!-- <BaseLoadingPlaceholder id="search_placeholder" text="Searching..." :hidden="true" /> -->
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#main_content {
|
||||
background-color: var(--main-background);
|
||||
min-width: 10px;
|
||||
// margin-left: 48px; // $sidebar-width
|
||||
// width: calc(100% - #{$sidebar-width});
|
||||
// flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import TheContent from '@components/TheContent.vue'
|
||||
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TheContent,
|
||||
BaseLoadingPlaceholder
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<header id="search">
|
||||
<header id="search" aria-label="searchbar">
|
||||
<div class="search__icon">
|
||||
<i class="material-icons">search</i>
|
||||
</div>
|
||||
@ -19,11 +19,66 @@
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
$icon-dimension: 2rem;
|
||||
$searchbar-height: 45px;
|
||||
|
||||
#search {
|
||||
background-color: var(--secondary-background);
|
||||
padding: 0 1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid transparent;
|
||||
transition: border 200ms ease-in-out;
|
||||
border-radius: 15px;
|
||||
margin: 10px 10px 20px 10px;
|
||||
|
||||
&:focus-within {
|
||||
border: 1px solid var(--foreground);
|
||||
}
|
||||
|
||||
.search__icon {
|
||||
width: $icon-dimension;
|
||||
height: $icon-dimension;
|
||||
|
||||
i {
|
||||
font-size: $icon-dimension;
|
||||
color: var(--foreground);
|
||||
}
|
||||
}
|
||||
|
||||
#searchbar {
|
||||
height: $searchbar-height;
|
||||
padding-left: 0.5em;
|
||||
border: 0px;
|
||||
border-radius: 0px;
|
||||
background-color: var(--secondary-background);
|
||||
color: var(--foreground);
|
||||
font-size: 1.2rem;
|
||||
font-family: 'Open Sans';
|
||||
font-weight: 300;
|
||||
margin-bottom: 0;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// Removing Chrome autofill color
|
||||
&:-webkit-autofill,
|
||||
&:-webkit-autofill:hover,
|
||||
&:-webkit-autofill:focus,
|
||||
&:-webkit-autofill:active {
|
||||
-webkit-box-shadow: 0 0 0 $searchbar-height var(--secondary-background) inset !important;
|
||||
box-shadow: 0 0 0 $searchbar-height var(--secondary-background) inset !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { isValidURL } from '@/utils/utils'
|
||||
import Downloads from '@/utils/downloads'
|
||||
|
||||
import EventBus from '@/utils/EventBus.js'
|
||||
import { sendAddToQueue } from '@/utils/downloads'
|
||||
import EventBus from '@/utils/EventBus'
|
||||
import { socket } from '@/utils/socket'
|
||||
|
||||
export default {
|
||||
@ -32,12 +87,27 @@ export default {
|
||||
lastTextSearch: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('keyup', keyEvent => {
|
||||
if (!(keyEvent.key == 'Backspace' && keyEvent.ctrlKey)) return
|
||||
created() {
|
||||
const focusSearchBar = keyEvent => {
|
||||
if (keyEvent.keyCode === 70 && keyEvent.ctrlKey) {
|
||||
keyEvent.preventDefault()
|
||||
this.$refs.searchbar.focus()
|
||||
}
|
||||
}
|
||||
|
||||
const deleteSearchBarContent = keyEvent => {
|
||||
if (!(keyEvent.key == 'Backspace' && keyEvent.ctrlKey && keyEvent.shiftKey)) return
|
||||
|
||||
this.$refs.searchbar.value = ''
|
||||
this.$refs.searchbar.focus()
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', focusSearchBar)
|
||||
document.addEventListener('keyup', deleteSearchBarContent)
|
||||
|
||||
this.$on('hook:destroyed', () => {
|
||||
document.removeEventListener('keydown', focusSearchBar)
|
||||
document.removeEventListener('keyup', deleteSearchBarContent)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
@ -71,11 +141,14 @@ export default {
|
||||
socket.emit('analyzeLink', term)
|
||||
} else {
|
||||
// ? Open downloads tab ?
|
||||
Downloads.sendAddToQueue(term)
|
||||
sendAddToQueue(term)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isShowingSearch && sameAsLastSearch) return
|
||||
if (isShowingSearch && sameAsLastSearch) {
|
||||
this.$root.$emit('mainSearch:updateResults', term)
|
||||
return
|
||||
}
|
||||
|
||||
if (!isShowingSearch) {
|
||||
await this.$router.push({
|
||||
@ -88,12 +161,11 @@ export default {
|
||||
this.lastTextSearch = term
|
||||
}
|
||||
|
||||
this.$root.$emit('mainSearch:showNewResults', term, window.main_selected)
|
||||
this.$root.$emit('mainSearch:showNewResults', term)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
<template>
|
||||
<aside id="sidebar" role="navigation">
|
||||
<aside id="sidebar" role="navigation" aria-label="sidebar">
|
||||
<router-link
|
||||
v-for="link in links"
|
||||
:key="link.id"
|
||||
tag="span"
|
||||
tag="a"
|
||||
class="main_tablinks"
|
||||
role="link"
|
||||
:id="link.id"
|
||||
:class="{ active: activeTablink === link.name }"
|
||||
:aria-label="link.ariaLabel"
|
||||
@ -13,7 +12,7 @@
|
||||
@click.native="activeTablink = link.name"
|
||||
>
|
||||
<i class="material-icons side_icon">{{ link.icon }}</i>
|
||||
<span class="main_tablinks_text">{{ link.label }}</span>
|
||||
<span class="main_tablinks_text">{{ $t(link.label) }}</span>
|
||||
</router-link>
|
||||
|
||||
<span id="theme_selector" class="main_tablinks" role="link" aria-label="theme selector">
|
||||
@ -67,9 +66,6 @@
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
const $t = this.$t.bind(this)
|
||||
const $tc = this.$tc.bind(this)
|
||||
|
||||
return {
|
||||
appOnline: null,
|
||||
activeTheme: 'light',
|
||||
@ -82,7 +78,7 @@ export default {
|
||||
ariaLabel: 'home',
|
||||
routerName: 'Home',
|
||||
icon: 'home',
|
||||
label: $t('sidebar.home')
|
||||
label: 'sidebar.home'
|
||||
},
|
||||
{
|
||||
id: 'main_search_tablink',
|
||||
@ -90,7 +86,7 @@ export default {
|
||||
ariaLabel: 'search',
|
||||
routerName: 'Search',
|
||||
icon: 'search',
|
||||
label: $t('sidebar.search')
|
||||
label: 'sidebar.search'
|
||||
},
|
||||
{
|
||||
id: 'main_charts_tablink',
|
||||
@ -98,7 +94,7 @@ export default {
|
||||
ariaLabel: 'charts',
|
||||
routerName: 'Charts',
|
||||
icon: 'show_chart',
|
||||
label: $t('sidebar.charts')
|
||||
label: 'sidebar.charts'
|
||||
},
|
||||
{
|
||||
id: 'main_favorites_tablink',
|
||||
@ -106,7 +102,7 @@ export default {
|
||||
ariaLabel: 'favorites',
|
||||
routerName: 'Favorites',
|
||||
icon: 'star',
|
||||
label: $t('sidebar.favorites')
|
||||
label: 'sidebar.favorites'
|
||||
},
|
||||
{
|
||||
id: 'main_analyzer_tablink',
|
||||
@ -114,7 +110,7 @@ export default {
|
||||
ariaLabel: 'link analyzer',
|
||||
routerName: 'Link Analyzer',
|
||||
icon: 'link',
|
||||
label: $t('sidebar.linkAnalyzer')
|
||||
label: 'sidebar.linkAnalyzer'
|
||||
},
|
||||
{
|
||||
id: 'main_settings_tablink',
|
||||
@ -122,7 +118,7 @@ export default {
|
||||
ariaLabel: 'settings',
|
||||
routerName: 'Settings',
|
||||
icon: 'settings',
|
||||
label: $t('sidebar.settings')
|
||||
label: 'sidebar.settings'
|
||||
},
|
||||
{
|
||||
id: 'main_about_tablink',
|
||||
@ -130,7 +126,7 @@ export default {
|
||||
ariaLabel: 'info',
|
||||
routerName: 'About',
|
||||
icon: 'info',
|
||||
label: $t('sidebar.about')
|
||||
label: 'sidebar.about'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
@transitionend="$refs.container.style.transition = ''"
|
||||
ref="container"
|
||||
:data-label="$t('downloads')"
|
||||
aria-label="downloads"
|
||||
>
|
||||
<div id="download_tab_drag_handler" @mousedown.prevent="startDrag" ref="dragHandler"></div>
|
||||
<i
|
||||
@ -16,7 +17,6 @@
|
||||
></i>
|
||||
<div id="queue_buttons">
|
||||
<i
|
||||
id="open_downloads_folder"
|
||||
v-if="clientMode"
|
||||
class="material-icons download_bar_icon"
|
||||
:title="$t('globals.open_downloads_folder')"
|
||||
@ -24,20 +24,10 @@
|
||||
>
|
||||
folder_open
|
||||
</i>
|
||||
<i
|
||||
id="clean_queue"
|
||||
class="material-icons download_bar_icon"
|
||||
@click="cleanQueue"
|
||||
:title="$t('globals.clean_queue_hint')"
|
||||
>
|
||||
<i class="material-icons download_bar_icon" @click="cleanQueue" :title="$t('globals.clean_queue_hint')">
|
||||
clear_all
|
||||
</i>
|
||||
<i
|
||||
id="cancel_queue"
|
||||
class="material-icons download_bar_icon"
|
||||
@click="cancelQueue"
|
||||
:title="$t('globals.cancel_queue_hint')"
|
||||
>
|
||||
<i class="material-icons download_bar_icon" @click="cancelQueue" :title="$t('globals.cancel_queue_hint')">
|
||||
delete_sweep
|
||||
</i>
|
||||
</div>
|
||||
@ -87,6 +77,19 @@ export default {
|
||||
clientMode: 'getClientMode'
|
||||
})
|
||||
},
|
||||
created() {
|
||||
const checkIfToggleBar = keyEvent => {
|
||||
if (!(keyEvent.ctrlKey && keyEvent.key === 'b')) return
|
||||
|
||||
this.toggleDownloadTab()
|
||||
}
|
||||
|
||||
document.addEventListener('keyup', checkIfToggleBar)
|
||||
|
||||
this.$on('hook:destroyed', () => {
|
||||
document.removeEventListener('keyup', checkIfToggleBar)
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
socket.on('startDownload', this.startDownload)
|
||||
socket.on('startConversion', this.startConversion)
|
||||
@ -263,7 +266,7 @@ export default {
|
||||
|
||||
this.queueComplete = []
|
||||
},
|
||||
toggleDownloadTab(clickEvent) {
|
||||
toggleDownloadTab() {
|
||||
this.setTabWidth()
|
||||
|
||||
this.$refs.container.style.transition = 'all 250ms ease-in-out'
|
||||
@ -337,4 +340,3 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -13,9 +13,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Downloads from '@/utils/downloads'
|
||||
import downloadQualities from '@js/qualities'
|
||||
import { sendAddToQueue } from '@/utils/downloads'
|
||||
import { generatePath, copyToClipboard } from '@/utils/utils'
|
||||
import { downloadQualities } from '@/data/qualities'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -95,10 +95,10 @@ export default {
|
||||
|
||||
downloadQualities.forEach((quality, index) => {
|
||||
options[quality.objName] = {
|
||||
label: `${this.$t('globals.download', {thing: quality.label})}`,
|
||||
label: `${this.$t('globals.download', { thing: quality.label })}`,
|
||||
show: false,
|
||||
position: nextValuePosition + index,
|
||||
action: this.tryToDownloadTrack.bind(null, quality.value)
|
||||
action: sendAddToQueue.bind(null, this.deezerHref, quality.value)
|
||||
}
|
||||
})
|
||||
|
||||
@ -123,7 +123,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
showMenu(contextMenuEvent) {
|
||||
// contextMenuEvent.preventDefault()
|
||||
const { pageX, pageY, target: elementClicked } = contextMenuEvent
|
||||
const path = generatePath(elementClicked)
|
||||
let deezerLink = null
|
||||
@ -213,9 +212,6 @@ export default {
|
||||
downloadQualities.forEach(quality => {
|
||||
this.options[quality.objName].show = true
|
||||
})
|
||||
},
|
||||
tryToDownloadTrack(qualityValue) {
|
||||
Downloads.sendAddToQueue(this.deezerHref, qualityValue)
|
||||
}
|
||||
}
|
||||
}
|
@ -47,7 +47,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="release in showTable" :key="release.id">
|
||||
<td class="inline-flex clickable" @click="albumView" :data-id="release.id">
|
||||
<router-link tag="td" class="inline-flex clickable" :to="{ name: 'Album', params: { id: release.id } }">
|
||||
<img
|
||||
class="rounded coverart"
|
||||
:src="release.cover_small"
|
||||
@ -58,7 +58,7 @@
|
||||
<i v-if="checkNewRelease(release.release_date)" class="material-icons" style="color: #ff7300">
|
||||
fiber_new
|
||||
</i>
|
||||
</td>
|
||||
</router-link>
|
||||
<td>{{ release.release_date }}</td>
|
||||
<td>{{ release.nb_song }}</td>
|
||||
<td @click.stop="addToQueue" :data-link="release.link" class="clickable">
|
||||
@ -69,7 +69,7 @@
|
||||
</table>
|
||||
|
||||
<footer>
|
||||
<button class="back-button" @click="backTab">{{ $t('globals.back') }}</button>
|
||||
<button class="back-button" @click="$router.back()">{{ $t('globals.back') }}</button>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
@ -78,7 +78,6 @@
|
||||
import { isEmpty, orderBy } from 'lodash-es'
|
||||
import { socket } from '@/utils/socket'
|
||||
import Downloads from '@/utils/downloads'
|
||||
import { showView, backTab } from '@js/tabs'
|
||||
import EventBus from '@/utils/EventBus'
|
||||
|
||||
export default {
|
||||
@ -97,8 +96,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
backTab,
|
||||
albumView: showView.bind(null, 'album'),
|
||||
reset() {
|
||||
this.title = 'Loading...'
|
||||
this.image = ''
|
||||
@ -125,11 +122,8 @@ export default {
|
||||
changeTab(tab) {
|
||||
this.currentTab = tab
|
||||
},
|
||||
getCurrentTab() {
|
||||
return this.currentTab
|
||||
},
|
||||
updateSelected() {
|
||||
window.currentStack.selected = this.currentTab
|
||||
// Last tab opened logic
|
||||
},
|
||||
checkNewRelease(date) {
|
||||
let g1 = new Date()
|
@ -71,20 +71,20 @@
|
||||
(track.title_version && track.title.indexOf(track.title_version) == -1 ? ' ' + track.title_version : '')
|
||||
}}
|
||||
</td>
|
||||
<td
|
||||
class="table__cell--medium table__cell--center breakline clickable"
|
||||
@click="artistView"
|
||||
:data-id="track.artist.id"
|
||||
<router-link
|
||||
tag="td"
|
||||
class="table__cell table__cell--medium table__cell--center breakline clickable"
|
||||
:to="{ name: 'Artist', params: { id: track.artist.id } }"
|
||||
>
|
||||
{{ track.artist.name }}
|
||||
</td>
|
||||
<td
|
||||
</router-link>
|
||||
<router-link
|
||||
tag="td"
|
||||
class="table__cell--medium table__cell--center breakline clickable"
|
||||
@click="albumView"
|
||||
:data-id="track.album.id"
|
||||
:to="{ name: 'Album', params: { id: track.album.id } }"
|
||||
>
|
||||
{{ track.album.title }}
|
||||
</td>
|
||||
</router-link>
|
||||
<td class="table__cell--small table__cell--center">
|
||||
{{ convertDuration(track.duration) }}
|
||||
</td>
|
||||
@ -107,7 +107,6 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { socket } from '@/utils/socket'
|
||||
import { showView } from '@js/tabs.js'
|
||||
import { sendAddToQueue } from '@/utils/downloads'
|
||||
import { convertDuration } from '@/utils/utils'
|
||||
|
||||
@ -136,8 +135,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
convertDuration,
|
||||
artistView: showView.bind(null, 'artist'),
|
||||
albumView: showView.bind(null, 'album'),
|
||||
playPausePreview(e) {
|
||||
EventBus.$emit('trackPreview:playPausePreview', e)
|
||||
},
|
@ -29,46 +29,25 @@
|
||||
<h1>{{ $t('favorites.noPlaylists') }}</h1>
|
||||
</div>
|
||||
<div class="release_grid" v-if="playlists.length > 0 || spotifyPlaylists > 0">
|
||||
<div v-for="release in playlists" class="release clickable" @click="playlistView" :data-id="release.id">
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium" />
|
||||
<div
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="addToQueue"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.title }}</p>
|
||||
<p class="secondary-text">
|
||||
{{
|
||||
`${$t('globals.by', { artist: release.creator.name })} - ${$tc(
|
||||
'globals.listTabs.trackN',
|
||||
release.nb_tracks
|
||||
)}`
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
v-for="release in spotifyPlaylists"
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in playlists"
|
||||
:key="release.id"
|
||||
class="release clickable"
|
||||
@click="spotifyPlaylistView"
|
||||
:data-id="release.id"
|
||||
:to="{ name: 'Playlist', params: { id: release.id } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium" />
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="addToQueue"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.title }}</p>
|
||||
<p class="secondary-text">
|
||||
@ -79,7 +58,37 @@
|
||||
)}`
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</router-link>
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in spotifyPlaylists"
|
||||
:key="release.id"
|
||||
class="release clickable"
|
||||
:to="{ name: 'Spotify Playlist', params: { id: release.id } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium" />
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="addToQueue"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.title }}</p>
|
||||
<p class="secondary-text">
|
||||
{{
|
||||
`${$t('globals.by', { artist: release.creator.name })} - ${$tc(
|
||||
'globals.listTabs.trackN',
|
||||
release.nb_tracks
|
||||
)}`
|
||||
}}
|
||||
</p>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -88,22 +97,29 @@
|
||||
<h1>{{ $t('favorites.noAlbums') }}</h1>
|
||||
</div>
|
||||
<div class="release_grid" v-if="albums.length > 0">
|
||||
<div v-for="release in albums" class="release clickable" @click="albumView" :data-id="release.id">
|
||||
<router-link
|
||||
tag="div"
|
||||
class="release clickable"
|
||||
v-for="release in albums"
|
||||
:key="release.id"
|
||||
:to="{ name: 'Album', params: { id: release.id } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="rounded coverart" :src="release.cover_medium" />
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="addToQueue"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.title }}</p>
|
||||
<p class="secondary-text">{{ `${$t('globals.by', { artist: release.artist.name })}` }}</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -112,21 +128,28 @@
|
||||
<h1>{{ $t('favorites.noArtists') }}</h1>
|
||||
</div>
|
||||
<div class="release_grid" v-if="artists.length > 0">
|
||||
<div v-for="release in artists" class="release clickable" @click="artistView" :data-id="release.id">
|
||||
<router-link
|
||||
tag="div"
|
||||
class="release clickable"
|
||||
v-for="release in artists"
|
||||
:key="release.id"
|
||||
:to="{ name: 'Artist', params: { id: release.id } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="circle coverart" :src="release.picture_medium" />
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="addToQueue"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.name }}</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -165,20 +188,20 @@
|
||||
(track.title_version && track.title.indexOf(track.title_version) == -1 ? ' ' + track.title_version : '')
|
||||
}}
|
||||
</td>
|
||||
<td
|
||||
class="table__cell--medium table__cell--center breakline clickable"
|
||||
@click="artistView"
|
||||
:data-id="track.artist.id"
|
||||
<router-link
|
||||
tag="td"
|
||||
class="table__cell table__cell--medium table__cell--center breakline clickable"
|
||||
:to="{ name: 'Artist', params: { id: track.artist.id } }"
|
||||
>
|
||||
{{ track.artist.name }}
|
||||
</td>
|
||||
<td
|
||||
</router-link>
|
||||
<router-link
|
||||
tag="td"
|
||||
class="table__cell--medium table__cell--center breakline clickable"
|
||||
@click="albumView"
|
||||
:data-id="track.album.id"
|
||||
:to="{ name: 'Album', params: { id: track.album.id } }"
|
||||
>
|
||||
{{ track.album.title }}
|
||||
</td>
|
||||
</router-link>
|
||||
<td class="table__cell--small">
|
||||
{{ convertDuration(track.duration) }}
|
||||
</td>
|
||||
@ -210,8 +233,6 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { showView } from '@js/tabs'
|
||||
|
||||
import { socket } from '@/utils/socket'
|
||||
import { sendAddToQueue } from '@/utils/downloads'
|
||||
import { convertDuration } from '@/utils/utils'
|
||||
@ -257,10 +278,6 @@ export default {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
artistView: showView.bind(null, 'artist'),
|
||||
albumView: showView.bind(null, 'album'),
|
||||
playlistView: showView.bind(null, 'playlist'),
|
||||
spotifyPlaylistView: showView.bind(null, 'spotifyplaylist'),
|
||||
playPausePreview(e) {
|
||||
EventBus.$emit('trackPreview:playPausePreview', e)
|
||||
},
|
@ -4,7 +4,6 @@
|
||||
|
||||
<section class="home_section" ref="notLogged" v-if="!isLoggedIn">
|
||||
<p id="home_not_logged_text">{{ $t('home.needTologin') }}</p>
|
||||
<!-- <button type="button" name="button" @click="openSettings">{{ $t('home.openSettings') }}</button> -->
|
||||
<router-link tag="button" name="button" :to="{ name: 'Settings' }">
|
||||
{{ $t('home.openSettings') }}
|
||||
</router-link>
|
||||
@ -13,24 +12,27 @@
|
||||
<section v-if="playlists.length" class="home_section">
|
||||
<h3 class="section_heading">{{ $t('home.sections.popularPlaylists') }}</h3>
|
||||
<div class="release_grid">
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in playlists"
|
||||
:key="release.id"
|
||||
class="release clickable"
|
||||
@click="playlistView"
|
||||
:data-id="release.id"
|
||||
:to="{ name: 'Playlist', params: { id: release.id } }"
|
||||
@keyup.enter.native="$router.push({ name: 'Playlist', params: { id: release.id } })"
|
||||
tabindex="0"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium" />
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="addToQueue"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.title }}</p>
|
||||
<p class="secondary-text">
|
||||
@ -41,35 +43,39 @@
|
||||
)}`
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="albums.length" class="home_section">
|
||||
<h3 class="section_heading">{{ $t('home.sections.popularAlbums') }}</h3>
|
||||
<div class="release_grid">
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in albums"
|
||||
:key="release.id"
|
||||
class="release clickable"
|
||||
@click="albumView"
|
||||
:to="{ name: 'Album', params: { id: release.id } }"
|
||||
@keyup.enter.native="$router.push({ name: 'Album', params: { id: release.id } })"
|
||||
:data-id="release.id"
|
||||
tabindex="0"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="rounded coverart" :src="release.cover_medium" />
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="addToQueue"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.title }}</p>
|
||||
<p class="secondary-text">{{ `${$t('globals.by', { artist: release.artist.name })}` }}</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@ -78,7 +84,6 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
import { showView } from '@js/tabs'
|
||||
import { sendAddToQueue } from '@/utils/downloads'
|
||||
import { getHomeData } from '@/data/home'
|
||||
|
||||
@ -95,15 +100,9 @@ export default {
|
||||
this.initHome(homeData)
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['isLoggedIn']),
|
||||
needToWait() {
|
||||
return this.getHomeData.albums.data.length === 0 && this.getHomeData.playlists.data.length === 0
|
||||
}
|
||||
...mapGetters(['isLoggedIn'])
|
||||
},
|
||||
methods: {
|
||||
artistView: showView.bind(null, 'artist'),
|
||||
albumView: showView.bind(null, 'album'),
|
||||
playlistView: showView.bind(null, 'playlist'),
|
||||
addToQueue(e) {
|
||||
sendAddToQueue(e.currentTarget.dataset.link)
|
||||
},
|
@ -25,24 +25,39 @@
|
||||
>
|
||||
<div>
|
||||
<h1>{{ title }}</h1>
|
||||
<h2 v-if="type == 'track'">
|
||||
<h2 v-if="type === 'track'">
|
||||
<i18n path="globals.by" tag="span">
|
||||
<span place="artist" class="clickable" @click="artistView" :data-id="data.artist.id">{{
|
||||
data.artist.name
|
||||
}}</span>
|
||||
<router-link
|
||||
tag="span"
|
||||
place="artist"
|
||||
class="clickable"
|
||||
:to="{ name: 'Artist', params: { id: data.artist.id } }"
|
||||
>
|
||||
{{ data.artist.name }}
|
||||
</router-link>
|
||||
</i18n>
|
||||
•
|
||||
<i18n path="globals.in" tag="span">
|
||||
<span place="album" class="clickable" @click="albumView" :data-id="data.album.id">{{
|
||||
data.album.title
|
||||
}}</span>
|
||||
<router-link
|
||||
tag="span"
|
||||
place="album"
|
||||
class="clickable"
|
||||
:to="{ name: 'Album', params: { id: data.album.id } }"
|
||||
>
|
||||
{{ data.album.title }}
|
||||
</router-link>
|
||||
</i18n>
|
||||
</h2>
|
||||
<h2 v-else-if="type == 'album'">
|
||||
<h2 v-else-if="type === 'album'">
|
||||
<i18n path="globals.by" tag="span">
|
||||
<span place="artist" class="clickable" @click="artistView" :data-id="data.artist.id">{{
|
||||
data.artist.name
|
||||
}}</span>
|
||||
<router-link
|
||||
tag="span"
|
||||
place="artist"
|
||||
class="clickable"
|
||||
:to="{ name: 'Artist', params: { id: data.artist.id } }"
|
||||
>
|
||||
{{ data.artist.name }}
|
||||
</router-link>
|
||||
</i18n>
|
||||
{{ ` • ${$tc('globals.listTabs.trackN', data.nb_tracks)}` }}
|
||||
</h2>
|
||||
@ -106,7 +121,9 @@
|
||||
</table>
|
||||
|
||||
<div v-if="type == 'album'">
|
||||
<button @click="albumView" :data-id="id">{{ $t('linkAnalyzer.table.tracklist') }}</button>
|
||||
<router-link tag="button" :to="{ name: 'Album', params: { id } }">
|
||||
{{ $t('linkAnalyzer.table.tracklist') }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div v-if="countries.length">
|
||||
<p v-for="country in countries">{{ country[0] }} - {{ country[1] }}</p>
|
||||
@ -117,7 +134,6 @@
|
||||
|
||||
<script>
|
||||
import { socket } from '@/utils/socket'
|
||||
import { showView } from '@js/tabs'
|
||||
import { convertDuration } from '@/utils/utils'
|
||||
import { COUNTRIES } from '@/utils/countries'
|
||||
import EventBus from '@/utils/EventBus'
|
||||
@ -137,8 +153,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
artistView: showView.bind(null, 'artist'),
|
||||
albumView: showView.bind(null, 'album'),
|
||||
convertDuration,
|
||||
reset() {
|
||||
this.title = 'Loading...'
|
@ -23,9 +23,6 @@
|
||||
:is="currentTab.component"
|
||||
:results="results"
|
||||
@add-to-queue="addToQueue"
|
||||
@artist-view="artistView"
|
||||
@album-view="albumView"
|
||||
@playlist-view="playlistView"
|
||||
@change-search-tab="changeSearchTab"
|
||||
></component>
|
||||
</keep-alive>
|
||||
@ -34,7 +31,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
|
||||
import BaseLoadingPlaceholder from '@components/globals/BaseLoadingPlaceholder.vue'
|
||||
import ResultsAll from '@components/search/ResultsAll.vue'
|
||||
import ResultsAlbums from '@components/search/ResultsAlbums.vue'
|
||||
import ResultsArtists from '@components/search/ResultsArtists.vue'
|
||||
@ -42,7 +39,6 @@ import ResultsPlaylists from '@components/search/ResultsPlaylists.vue'
|
||||
import ResultsTracks from '@components/search/ResultsTracks.vue'
|
||||
|
||||
import { socket } from '@/utils/socket'
|
||||
import { showView } from '@js/tabs'
|
||||
import { sendAddToQueue } from '@/utils/downloads'
|
||||
import { numberWithDots, convertDuration } from '@/utils/utils'
|
||||
import EventBus from '@/utils/EventBus'
|
||||
@ -156,14 +152,12 @@ export default {
|
||||
mounted() {
|
||||
EventBus.$on('mainSearch:checkLoadMoreContent', this.checkLoadMoreContent)
|
||||
this.$root.$on('mainSearch:showNewResults', this.checkIfShowNewResults)
|
||||
this.$root.$on('mainSearch:updateResults', this.checkIfUpdateResults)
|
||||
|
||||
socket.on('mainSearch', this.handleMainSearch)
|
||||
socket.on('search', this.handleSearch)
|
||||
},
|
||||
methods: {
|
||||
artistView: showView.bind(null, 'artist'),
|
||||
albumView: showView.bind(null, 'album'),
|
||||
playlistView: showView.bind(null, 'playlist'),
|
||||
changeSearchTab(sectionName) {
|
||||
sectionName = sectionName.toLowerCase()
|
||||
|
||||
@ -180,12 +174,21 @@ export default {
|
||||
this.currentTab = newTab
|
||||
},
|
||||
checkIfShowNewResults(term, mainSelected) {
|
||||
let needToPerformNewSearch = term !== this.results.query || mainSelected == 'search_tab'
|
||||
let needToPerformNewSearch = term !== this.results.query /* || mainSelected == 'search_tab' */
|
||||
|
||||
if (needToPerformNewSearch) {
|
||||
this.showNewResults(term)
|
||||
}
|
||||
},
|
||||
checkIfUpdateResults(term) {
|
||||
let needToUpdateSearch = term === this.results.query && this.currentTab.searchType !== 'all'
|
||||
|
||||
if (needToUpdateSearch) {
|
||||
let resetObj = { data: [], next: 0, total: 0, loaded: false }
|
||||
this.results[this.currentTab.searchType + 'Tab'] = { ...resetObj }
|
||||
this.search(this.currentTab.searchType)
|
||||
}
|
||||
},
|
||||
showNewResults(term) {
|
||||
socket.emit('mainSearch', { term })
|
||||
|
@ -56,6 +56,7 @@
|
||||
:class="{ 'locale-flag--current': currentLocale === locale }"
|
||||
@click="changeLocale(locale)"
|
||||
v-html="flags[locale]"
|
||||
:title="locale"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
@ -187,7 +188,7 @@
|
||||
|
||||
<div class="input_group">
|
||||
<p class="input_group_text">{{ $t('settings.downloads.queueConcurrency') }}</p>
|
||||
<input type="number" v-model.number="settings.queueConcurrency" />
|
||||
<input type="number" min="1" v-model.number="settings.queueConcurrency" />
|
||||
</div>
|
||||
|
||||
<div class="input_group">
|
||||
@ -643,8 +644,8 @@
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
filter: brightness(0.5);
|
||||
}
|
||||
}
|
||||
@ -653,19 +654,18 @@
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
|
||||
import { getSettingsData } from '@/data/settings'
|
||||
|
||||
import { toast } from '@/utils/toasts'
|
||||
import { socket } from '@/utils/socket'
|
||||
import EventBus from '@/utils/EventBus'
|
||||
import flags from '@/utils/flags'
|
||||
|
||||
import { getSettingsData } from '@/data/settings'
|
||||
import { flags } from '@/utils/flags'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
flags,
|
||||
currentLocale: 'en',
|
||||
locales: [],
|
||||
currentLocale: this.$i18n.locale,
|
||||
locales: this.$i18n.availableLocales,
|
||||
settings: {
|
||||
tags: {}
|
||||
},
|
||||
@ -679,7 +679,6 @@ export default {
|
||||
previewVolume: window.vol,
|
||||
accountNum: 0,
|
||||
accounts: []
|
||||
// clientMode: window.clientMode
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -708,23 +707,11 @@ export default {
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.locales = this.$i18n.availableLocales
|
||||
|
||||
const { settingsData, defaultSettingsData, spotifyCredentials } = await getSettingsData()
|
||||
|
||||
this.defaultSettings = defaultSettingsData
|
||||
this.initSettings(settingsData, spotifyCredentials)
|
||||
|
||||
// this.revertSettings()
|
||||
// this.revertCredentials()
|
||||
|
||||
let storedLocale = localStorage.getItem('locale')
|
||||
|
||||
if (storedLocale) {
|
||||
this.$i18n.locale = storedLocale
|
||||
this.currentLocale = storedLocale
|
||||
}
|
||||
|
||||
let storedAccountNum = localStorage.getItem('accountNum')
|
||||
|
||||
if (storedAccountNum) {
|
||||
@ -823,6 +810,11 @@ export default {
|
||||
this.lastCredentials = JSON.parse(JSON.stringify(credentials))
|
||||
this.spotifyFeatures = JSON.parse(JSON.stringify(credentials))
|
||||
},
|
||||
loggedInViaDeezer(arl) {
|
||||
this.dispatchARL({ arl })
|
||||
socket.emit('login', arl, true, this.accountNum)
|
||||
// this.login()
|
||||
},
|
||||
login() {
|
||||
let newArl = this.$refs.loginInput.value.trim()
|
||||
|
||||
@ -833,10 +825,6 @@ export default {
|
||||
appLogin(e) {
|
||||
socket.emit('applogin')
|
||||
},
|
||||
loggedInViaDeezer(arl) {
|
||||
this.dispatchARL({ arl })
|
||||
this.login()
|
||||
},
|
||||
changeAccount() {
|
||||
socket.emit('changeAccount', this.accountNum)
|
||||
},
|
@ -64,21 +64,21 @@
|
||||
}}
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
<router-link
|
||||
tag="td"
|
||||
class="table__cell--medium table__cell--center clickable"
|
||||
@click="artistView"
|
||||
:data-id="track.artist.id"
|
||||
:to="{ name: 'Artist', params: { id: track.artist.id } }"
|
||||
>
|
||||
{{ track.artist.name }}
|
||||
</td>
|
||||
<td
|
||||
v-if="type == 'playlist'"
|
||||
</router-link>
|
||||
<router-link
|
||||
tag="td"
|
||||
v-if="type === 'playlist'"
|
||||
class="table__cell--medium table__cell--center clickable"
|
||||
@click="albumView"
|
||||
:data-id="track.album.id"
|
||||
:to="{ name: 'Album', params: { id: track.album.id } }"
|
||||
>
|
||||
{{ track.album.title }}
|
||||
</td>
|
||||
</router-link>
|
||||
<td
|
||||
class="table__cell--center"
|
||||
:class="{ 'table__cell--small': type === 'album', 'table__cell--x-small': type === 'playlist' }"
|
||||
@ -137,7 +137,7 @@
|
||||
<button class="with_icon" @click.stop="addToQueue" :data-link="selectedLinks()">
|
||||
{{ $t('tracklist.downloadSelection') }}<i class="material-icons">file_download</i>
|
||||
</button>
|
||||
<button class="back-button" @click="backTab">{{ $t('globals.back') }}</button>
|
||||
<button class="back-button" @click="$router.back()">{{ $t('globals.back') }}</button>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
@ -145,28 +145,25 @@
|
||||
<script>
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { socket } from '@/utils/socket'
|
||||
import { showView, backTab } from '@js/tabs.js'
|
||||
import Downloads from '@/utils/downloads'
|
||||
import Utils from '@/utils/utils'
|
||||
import EventBus from '@/utils/EventBus'
|
||||
|
||||
export default {
|
||||
name: 'tracklist-tab',
|
||||
data: () => ({
|
||||
title: '',
|
||||
metadata: '',
|
||||
release_date: '',
|
||||
label: '',
|
||||
explicit: false,
|
||||
image: '',
|
||||
type: 'empty',
|
||||
link: '',
|
||||
body: []
|
||||
}),
|
||||
data() {
|
||||
return {
|
||||
title: '',
|
||||
metadata: '',
|
||||
release_date: '',
|
||||
label: '',
|
||||
explicit: false,
|
||||
image: '',
|
||||
type: 'empty',
|
||||
link: '',
|
||||
body: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
backTab,
|
||||
artistView: showView.bind(null, 'artist'),
|
||||
albumView: showView.bind(null, 'album'),
|
||||
playPausePreview(e) {
|
||||
EventBus.$emit('trackPreview:playPausePreview', e)
|
||||
},
|
@ -5,23 +5,25 @@
|
||||
<h1>{{ $t('search.noResultsAlbum') }}</h1>
|
||||
</div>
|
||||
<div class="release_grid" v-if="results.albumTab.data.length > 0">
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in results.albumTab.data"
|
||||
:key="release.id"
|
||||
class="release clickable"
|
||||
@click.stop="$emit('album-view', $event)"
|
||||
:data-id="release.id"
|
||||
:to="{ name: 'Album', params: { id: release.id } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="rounded coverart" :src="release.cover_medium" />
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="$emit('add-to-queue', $event)"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text inline-flex">
|
||||
<i v-if="release.explicit_lyrics" class="material-icons explicit_icon">explicit</i>
|
||||
@ -34,13 +36,13 @@
|
||||
$tc('globals.listTabs.trackN', release.nb_tracks)
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
|
||||
import BaseLoadingPlaceholder from '@components/globals/BaseLoadingPlaceholder.vue'
|
||||
|
||||
export default {
|
||||
props: ['results'],
|
||||
|
@ -15,11 +15,11 @@
|
||||
{{ $tc(`globals.listTabs.${section.toLowerCase()}`, 2) }}
|
||||
</h2>
|
||||
<!-- Top result -->
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-if="section == 'TOP_RESULT'"
|
||||
class="top_result clickable"
|
||||
@click.stop="$emit(`${topResultType}-view`, $event)"
|
||||
:data-id="results.allTab.TOP_RESULT[0].id"
|
||||
:to="{ name: upperCaseFirstLowerCaseRest(topResultType), params: { id: results.allTab.TOP_RESULT[0].id } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img
|
||||
@ -27,34 +27,29 @@
|
||||
:src="results.allTab.TOP_RESULT[0].picture"
|
||||
:class="(results.allTab.TOP_RESULT[0].type == 'artist' ? 'circle' : 'rounded') + ' coverart'"
|
||||
/>
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="$emit('add-to-queue', $event)"
|
||||
:data-link="results.allTab.TOP_RESULT[0].link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="info_box">
|
||||
<p class="primary-text">{{ results.allTab.TOP_RESULT[0].title }}</p>
|
||||
<p class="secondary-text">
|
||||
{{
|
||||
results.allTab.TOP_RESULT[0].type == 'artist'
|
||||
? $t('search.fans', { n: $n(results.allTab.TOP_RESULT[0].nb_fan) })
|
||||
: $t('globals.by', { artist: results.allTab.TOP_RESULT[0].artist }) +
|
||||
' - ' +
|
||||
$tc('globals.listTabs.trackN', results.allTab.TOP_RESULT[0].nb_song)
|
||||
}}
|
||||
{{ fansNumber }}
|
||||
</p>
|
||||
<span class="tag">{{ $tc(`globals.listTabs.${results.allTab.TOP_RESULT[0].type}`, 1) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</router-link>
|
||||
<div v-else-if="section == 'TRACK'">
|
||||
<table class="table table--tracks">
|
||||
<tbody>
|
||||
<tr v-for="track in results.allTab.TRACK.data.slice(0, 6)">
|
||||
<tr v-for="track in results.allTab.TRACK.data.slice(0, 6)" :key="track.SNG_ID">
|
||||
<td class="table__icon" aria-hidden="true">
|
||||
<img
|
||||
class="rounded coverart"
|
||||
@ -70,23 +65,26 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="table__cell table__cell--medium table__cell--center breakline">
|
||||
<span
|
||||
class="clickable"
|
||||
@click.stop="$emit('artist-view', $event)"
|
||||
:data-id="artist.ART_ID"
|
||||
<router-link
|
||||
tag="span"
|
||||
v-for="artist in track.ARTISTS"
|
||||
:key="artist.ART_ID"
|
||||
class="clickable"
|
||||
:to="{
|
||||
name: 'Artist',
|
||||
params: { id: artist.ART_ID }
|
||||
}"
|
||||
>
|
||||
{{ artist.ART_NAME }}
|
||||
</span>
|
||||
</router-link>
|
||||
</td>
|
||||
<td
|
||||
<router-link
|
||||
tag="td"
|
||||
class="table__cell--medium table__cell--center breakline clickable"
|
||||
@click.stop="$emit('album-view', $event)"
|
||||
:data-id="track.ALB_ID"
|
||||
:to="{ name: 'Album', params: { id: track.ALB_ID } }"
|
||||
>
|
||||
{{ track.ALB_TITLE }}
|
||||
</td>
|
||||
</router-link>
|
||||
<td class="table__cell table__cell--center">
|
||||
{{ convertDuration(track.DURATION) }}
|
||||
</td>
|
||||
@ -104,11 +102,12 @@
|
||||
</table>
|
||||
</div>
|
||||
<div v-else-if="section == 'ARTIST'" class="release_grid firstrow_only">
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in results.allTab.ARTIST.data.slice(0, 10)"
|
||||
class="release clickable"
|
||||
@click.stop="$emit('artist-view', $event)"
|
||||
:data-id="release.ART_ID"
|
||||
:key="release.ART_ID"
|
||||
:to="{ name: 'Artist', params: { id: release.ART_ID } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img
|
||||
@ -118,26 +117,28 @@
|
||||
'https://e-cdns-images.dzcdn.net/images/artist/' + release.ART_PICTURE + '/156x156-000000-80-0-0.jpg'
|
||||
"
|
||||
/>
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="$emit('add-to-queue', $event)"
|
||||
:data-link="'https://deezer.com/artist/' + release.ART_ID"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.ART_NAME }}</p>
|
||||
<p class="secondary-text">{{ $t('search.fans', { n: $n(release.NB_FAN) }) }}</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
<div v-else-if="section == 'ALBUM'" class="release_grid firstrow_only">
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in results.allTab.ALBUM.data.slice(0, 10)"
|
||||
:key="release.ALB_ID"
|
||||
class="release clickable"
|
||||
@click.stop="$emit('album-view', $event)"
|
||||
:data-id="release.ALB_ID"
|
||||
:to="{ name: 'Album', params: { id: release.ALB_ID } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img
|
||||
@ -147,15 +148,16 @@
|
||||
'https://e-cdns-images.dzcdn.net/images/cover/' + release.ALB_PICTURE + '/156x156-000000-80-0-0.jpg'
|
||||
"
|
||||
/>
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="$emit('add-to-queue', $event)"
|
||||
:data-link="'https://deezer.com/album/' + release.ALB_ID"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text inline-flex">
|
||||
<i
|
||||
@ -168,14 +170,15 @@
|
||||
<p class="secondary-text">
|
||||
{{ release.ART_NAME + ' - ' + $tc('globals.listTabs.trackN', release.NUMBER_TRACK) }}
|
||||
</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
<div v-else-if="section == 'PLAYLIST'" class="release_grid firstrow_only">
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in results.allTab.PLAYLIST.data.slice(0, 10)"
|
||||
class="release clickable"
|
||||
@click.stop="$emit('playlist-view', $event)"
|
||||
:data-id="release.PLAYLIST_ID"
|
||||
:key="release.PLAYLIST_ID"
|
||||
:to="{ name: 'Playlist', params: { id: release.PLAYLIST_ID } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img
|
||||
@ -189,19 +192,20 @@
|
||||
'/156x156-000000-80-0-0.jpg'
|
||||
"
|
||||
/>
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="$emit('add-to-queue', $event)"
|
||||
:data-link="'https://deezer.com/playlist/' + release.PLAYLIST_ID"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.TITLE }}</p>
|
||||
<p class="secondary-text">{{ $tc('globals.listTabs.trackN', release.NB_SONG) }}</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@ -212,6 +216,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { convertDuration } from '@/utils/utils'
|
||||
import { upperCaseFirstLowerCaseRest } from '@/utils/texts'
|
||||
|
||||
export default {
|
||||
props: ['results'],
|
||||
@ -225,10 +230,26 @@ export default {
|
||||
? this.results.allTab[section].length == 0
|
||||
: this.results.allTab[section].data.length == 0
|
||||
)
|
||||
},
|
||||
fansNumber() {
|
||||
let number
|
||||
|
||||
try {
|
||||
number = this.$n(this.results.allTab.TOP_RESULT[0].nb_fan)
|
||||
} catch (error) {
|
||||
number = this.$n(this.results.allTab.TOP_RESULT[0].nb_fan, { locale: 'en' })
|
||||
}
|
||||
|
||||
return this.results.allTab.TOP_RESULT[0].type == 'artist'
|
||||
? this.$t('search.fans', { n: number })
|
||||
: this.$t('globals.by', { artist: this.results.allTab.TOP_RESULT[0].artist }) +
|
||||
' - ' +
|
||||
this.$tc('globals.listTabs.trackN', this.results.allTab.TOP_RESULT[0].nb_song)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
convertDuration
|
||||
convertDuration,
|
||||
upperCaseFirstLowerCaseRest
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,37 +1,39 @@
|
||||
<template>
|
||||
<div id="artist_search" class="search_tabcontent">
|
||||
<base-loading-placeholder v-if="!results.artistTab.loaded"></base-loading-placeholder>
|
||||
<BaseLoadingPlaceholder v-if="!results.artistTab.loaded"></BaseLoadingPlaceholder>
|
||||
<div v-else-if="results.artistTab.data.length == 0">
|
||||
<h1>{{ $t('search.noResultsArtist') }}</h1>
|
||||
</div>
|
||||
<div class="release_grid" v-if="results.artistTab.data.length > 0">
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in results.artistTab.data"
|
||||
class="release clickable"
|
||||
@click.stop="$emit('artist-view', $event)"
|
||||
:data-id="release.id"
|
||||
:key="release.id"
|
||||
:to="{ name: 'Artist', params: { id: release.id } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="circle coverart" :src="release.picture_medium" />
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="$emit('add-to-queue', $event)"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.name }}</p>
|
||||
<p class="secondary-text">{{ $tc('globals.listTabs.releaseN', release.nb_album) }}</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
|
||||
import BaseLoadingPlaceholder from '@components/globals/BaseLoadingPlaceholder.vue'
|
||||
|
||||
export default {
|
||||
props: ['results'],
|
||||
|
@ -5,23 +5,25 @@
|
||||
<h1>{{ $t('search.noResultsPlaylist') }}</h1>
|
||||
</div>
|
||||
<div class="release_grid" v-if="results.playlistTab.data.length > 0">
|
||||
<div
|
||||
<router-link
|
||||
tag="div"
|
||||
v-for="release in results.playlistTab.data"
|
||||
class="release clickable"
|
||||
@click.stop="$emit('playlist-view', $event)"
|
||||
:data-id="release.id"
|
||||
:key="release.id"
|
||||
:to="{ name: 'Playlist', params: { id: release.id } }"
|
||||
>
|
||||
<div class="cover_container">
|
||||
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium" />
|
||||
<div
|
||||
<button
|
||||
role="button"
|
||||
aria-label="download"
|
||||
@click.stop="$emit('add-to-queue', $event)"
|
||||
:data-link="release.link"
|
||||
class="download_overlay"
|
||||
tabindex="0"
|
||||
>
|
||||
<i class="material-icons" :title="$t('globals.download_hint')">get_app</i>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<p class="primary-text">{{ release.title }}</p>
|
||||
<p class="secondary-text">
|
||||
@ -29,13 +31,13 @@
|
||||
`${$t('globals.by', { artist: release.user.name })} - ${$tc('globals.listTabs.trackN', release.nb_tracks)}`
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
|
||||
import BaseLoadingPlaceholder from '@components/globals/BaseLoadingPlaceholder.vue'
|
||||
|
||||
export default {
|
||||
props: ['results'],
|
||||
|
@ -46,20 +46,20 @@
|
||||
}}
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
<router-link
|
||||
tag="td"
|
||||
class="table__cell table__cell--medium table__cell--center breakline clickable"
|
||||
@click.stop="artistView"
|
||||
:data-id="track.artist.id"
|
||||
:to="{ name: 'Artist', params: { id: track.artist.id } }"
|
||||
>
|
||||
{{ track.artist.name }}
|
||||
</td>
|
||||
<td
|
||||
</router-link>
|
||||
<router-link
|
||||
tag="td"
|
||||
class="table__cell table__cell--medium table__cell--center breakline clickable"
|
||||
@click.stop="albumView"
|
||||
:data-id="track.album.id"
|
||||
:to="{ name: 'Album', params: { id: track.album.id } }"
|
||||
>
|
||||
{{ track.album.title }}
|
||||
</td>
|
||||
</router-link>
|
||||
<td class="table__cell table__cell--small table__cell--center">
|
||||
{{ convertDuration(track.duration) }}
|
||||
</td>
|
||||
@ -79,9 +79,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseLoadingPlaceholder from '@components/BaseLoadingPlaceholder.vue'
|
||||
import BaseLoadingPlaceholder from '@components/globals/BaseLoadingPlaceholder.vue'
|
||||
|
||||
import EventBus from '@/utils/EventBus.js'
|
||||
import EventBus from '@/utils/EventBus'
|
||||
import { convertDuration } from '@/utils/utils'
|
||||
|
||||
export default {
|
||||
@ -91,15 +91,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
convertDuration,
|
||||
artistView(event) {
|
||||
this.$emit('artist-view', event)
|
||||
},
|
||||
albumView(event) {
|
||||
this.$emit('album-view', event)
|
||||
},
|
||||
playlistView(event) {
|
||||
this.$emit('playlist-view', event)
|
||||
},
|
||||
playPausePreview(e) {
|
||||
EventBus.$emit('trackPreview:playPausePreview', e)
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
export default [
|
||||
export const downloadQualities = [
|
||||
{
|
||||
objName: 'flac',
|
||||
label: 'FLAC',
|
@ -1,93 +0,0 @@
|
||||
import EventBus from '@/utils/EventBus'
|
||||
import router from '@/router'
|
||||
|
||||
/* ===== Globals ====== */
|
||||
window.search_selected = ''
|
||||
window.main_selected = ''
|
||||
window.windows_stack = []
|
||||
window.currentStack = {}
|
||||
|
||||
// Used only in errors tab
|
||||
export function changeTab(sidebarEl, section, tabName) {
|
||||
window.windows_stack = []
|
||||
window.currentStack = {}
|
||||
|
||||
// * Only in section search
|
||||
updateTabLink(section)
|
||||
|
||||
// * Only when clicking the settings icon in the sidebar
|
||||
// resetSettings(tabName)
|
||||
|
||||
// * Only in section search
|
||||
setSelectedTab(section, tabName)
|
||||
|
||||
// * Only if window.main_selected === 'search_tab'
|
||||
checkNeedToLoadMoreContent()
|
||||
}
|
||||
|
||||
function setSelectedTab(section, tabName) {
|
||||
if (section === 'main') {
|
||||
window.main_selected = tabName
|
||||
} else if (section === 'search') {
|
||||
window.search_selected = tabName
|
||||
}
|
||||
}
|
||||
|
||||
function checkNeedToLoadMoreContent() {
|
||||
// * Check if you need to load more content in the search tab
|
||||
// * Happens when the user changes the tab in the main search
|
||||
if (
|
||||
window.main_selected === 'search_tab' &&
|
||||
['track_search', 'album_search', 'artist_search', 'playlist_search'].indexOf(window.search_selected) !== -1
|
||||
) {
|
||||
EventBus.$emit('mainSearch:checkLoadMoreContent', window.search_selected)
|
||||
}
|
||||
}
|
||||
|
||||
function resetSettings(tabName) {
|
||||
if (tabName === 'settings_tab' && window.main_selected !== 'settings_tab') {
|
||||
EventBus.$emit('settingsTab:revertSettings')
|
||||
EventBus.$emit('settingsTab:revertCredentials')
|
||||
}
|
||||
}
|
||||
|
||||
function updateTabLink(section) {
|
||||
// * Tabs inside the actual tab (like albums, tracks, playlists...)
|
||||
// * or sidebar links
|
||||
if (section == 'main') return
|
||||
|
||||
const tabLinks = document.getElementsByClassName(`${section}_tablinks`)
|
||||
|
||||
for (let i = 0; i < tabLinks.length; i++) {
|
||||
tabLinks[i].classList.remove('active')
|
||||
}
|
||||
}
|
||||
|
||||
export function showView(viewType, event) {
|
||||
const {
|
||||
currentTarget: {
|
||||
dataset: { id }
|
||||
}
|
||||
} = event
|
||||
const isArtist = viewType === 'artist'
|
||||
const name = isArtist ? 'Artist' : 'Tracklist'
|
||||
const params = isArtist ? { id } : { type: viewType, id }
|
||||
|
||||
router.push({
|
||||
name,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes back to the previous tab according to the global window stack.
|
||||
*/
|
||||
export function backTab() {
|
||||
// ! Need to implement the memory of the opened artist tab
|
||||
router.back()
|
||||
}
|
||||
|
||||
export function init() {
|
||||
// Open default tab
|
||||
changeTab(document.getElementById('main_home_tablink'), 'main', 'home_tab')
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"],
|
||||
"@js/*": ["./js/*"],
|
||||
"@components/*": ["./components/*"]
|
||||
}
|
||||
},
|
||||
|
@ -105,7 +105,8 @@ const en = {
|
||||
no360RA: 'Track is not available in Reality Audio 360.',
|
||||
notAvailable: "Track not available on Deezer's servers!",
|
||||
notAvailableNoAlternative: "Track not available on Deezer's servers and no alternative found!",
|
||||
noSpaceLeft: "No space left on the device!"
|
||||
noSpaceLeft: "No space left on the device!",
|
||||
albumDoesntExists: "Track's album doesn't exist, failed to gather info"
|
||||
}
|
||||
},
|
||||
favorites: {
|
||||
|
@ -105,7 +105,8 @@ const fr = {
|
||||
no360RA: 'La piste est indisponible au format Reality Audio 360.',
|
||||
notAvailable: 'La piste est indisponible sur les serveurs de Deezer !',
|
||||
notAvailableNoAlternative: "La piste est indisponible sur les serveurs de Deezer et aucune alternative n'a été trouvée !",
|
||||
noSpaceLeft: "L'espace disponible sur cet appareil est insuffisant !"
|
||||
noSpaceLeft: "L'espace disponible sur cet appareil est insuffisant !",
|
||||
albumDoesntExists: "Aucun album n'existe pour cette piste, impossible de collecter les informations nécessaires"
|
||||
}
|
||||
},
|
||||
favorites: {
|
||||
|
33
src/lang/index.js
Normal file
33
src/lang/index.js
Normal file
@ -0,0 +1,33 @@
|
||||
import it from '@/lang/it'
|
||||
import en from '@/lang/en'
|
||||
import es from '@/lang/es'
|
||||
import de from '@/lang/de'
|
||||
import fr from '@/lang/fr'
|
||||
import id from '@/lang/id'
|
||||
import pt from '@/lang/pt-pt'
|
||||
import pt_br from '@/lang/pt-br'
|
||||
import ru from '@/lang/ru'
|
||||
import tr from '@/lang/tr'
|
||||
import vn from '@/lang/vn'
|
||||
import hr from '@/lang/hr'
|
||||
import ar from '@/lang/ar'
|
||||
import ko from '@/lang/ko'
|
||||
import ph from '@/lang/ph'
|
||||
|
||||
export const locales = {
|
||||
it,
|
||||
en,
|
||||
es,
|
||||
de,
|
||||
fr,
|
||||
id,
|
||||
pt,
|
||||
pt_br,
|
||||
ru,
|
||||
tr,
|
||||
vn,
|
||||
hr,
|
||||
ar,
|
||||
ko,
|
||||
ph
|
||||
}
|
@ -108,7 +108,8 @@ const it = {
|
||||
no360RA: 'Brano non disponibile in Reality Audio 360.',
|
||||
notAvailable: 'Brano non presente sui server di Deezer!',
|
||||
notAvailableNoAlternative: 'Brano non presente sui server di Deezer e nessuna alternativa trovata!',
|
||||
noSpaceLeft: "Spazio su disco esaurito!"
|
||||
noSpaceLeft: "Spazio su disco esaurito!",
|
||||
albumDoesntExists: "Il brano non ha nessun album, impossibile ottenere informazioni"
|
||||
}
|
||||
},
|
||||
favorites: {
|
||||
|
@ -97,7 +97,7 @@ const ko = {
|
||||
wrongBitrateNoAlternative: '요구하는 비트레이트를 찾을 수 없을 뿐더러 대체할 것을 찾지 못했습니다!',
|
||||
no360RA: '해당 트랙은 360 리얼리티 오디오에 존재하지 않습니다.',
|
||||
notAvailable: "해당 트랙은 Deezer 서버에 존재하지 않습니다!",
|
||||
notAvailableNoAlternative: "해당 트랙은 Deezer 서버에 존재하지 않을 뿐더러 대체할 것을 찾지 못했습니다!"
|
||||
notAvailableNoAlternative: "해당 트랙은 Deezer 서버에 존재하지 않을 뿐더러 대체할 것을 찾지 못했습니다!",
|
||||
noSpaceLeft: "장치에 여유 공간이 없습니다!"
|
||||
}
|
||||
},
|
||||
@ -168,7 +168,7 @@ const ko = {
|
||||
finishAddingArtist: '{artist} 앨범이 대기열에 추가되었습니다',
|
||||
startConvertingSpotifyPlaylist: '스포티파이 트랙을 Deezer 트랙으로 전환 중입니다',
|
||||
finishConvertingSpotifyPlaylist: '스프토파이 재생 목록이 전환되었습니다',
|
||||
loginNeededToDownload: '트랙을 다운로드하려면 로그인이 필요합니다!'
|
||||
loginNeededToDownload: '트랙을 다운로드하려면 로그인이 필요합니다!',
|
||||
deezerNotAvailable: 'Deezer 사이트는 현재 귀하의 국가에서 사용이 불가능합니다. VPN을 사용하세요.'
|
||||
},
|
||||
settings: {
|
||||
@ -181,8 +181,8 @@ const ko = {
|
||||
question: 'ARL을 어떻게 확인합니까?',
|
||||
update: 'ARL 업데이트'
|
||||
},
|
||||
logout: '로그아웃'
|
||||
question: '스포티파이 기능들을 쓰려면 어떻게 해야합니까?
|
||||
logout: '로그아웃',
|
||||
question: '스포티파이 기능들을 쓰려면 어떻게 해야합니까?'
|
||||
},
|
||||
appearance: {
|
||||
title: '외관',
|
||||
@ -258,7 +258,7 @@ const ko = {
|
||||
jpegImageQuality: 'JPEG 이미지 품질',
|
||||
embeddedArtworkPNG: '포함된 그림의 형식을 PNG로 저장합니다',
|
||||
embeddedPNGWarning: 'PNG는 Deezer에서 공식적으로 지원하지 않기 때문에 버그가 있을 수 있습니다',
|
||||
imageSizeWarning: 'x1200 크기를 초과해서는 Deezer에서 공식적으로 사용되지 않기 때문에 문제가 생길 수 있습니다'
|
||||
imageSizeWarning: 'x1200 크기를 초과해서는 Deezer에서 공식적으로 사용되지 않기 때문에 문제가 생길 수 있습니다',
|
||||
coverDescriptionUTF8: '커버 설명을 UTF8 포맷을 이용해 저장합니다 (iTunes 커버 오류 해결)'
|
||||
},
|
||||
tags: {
|
||||
|
371
src/lang/ph.js
Normal file
371
src/lang/ph.js
Normal file
@ -0,0 +1,371 @@
|
||||
const ph = {
|
||||
globals: {
|
||||
welcome: 'Welcome sa deemix',
|
||||
back: 'bumalik',
|
||||
loading: 'kumakarga',
|
||||
download: 'I-download {thing}',
|
||||
by: 'ayon sa {artist}',
|
||||
in: 'sa {album}',
|
||||
download_hint: 'I-download',
|
||||
play_hint: 'I-play',
|
||||
toggle_download_tab_hint: 'Palakihin/Paliitan',
|
||||
clean_queue_hint: 'Natapos na ang Pag-alis',
|
||||
cancel_queue_hint: 'Ikansel Lahat',
|
||||
open_downloads_folder: 'Buksan ang Polder ng Download',
|
||||
cut: 'i-cut',
|
||||
copy: 'kopyahin',
|
||||
copyLink: 'kopyahin ang link',
|
||||
copyImageLink: 'kopyahin ang imahe sa link',
|
||||
copyDeezerLink: 'kopyahin ang link ng deezer',
|
||||
paste: 'idikit',
|
||||
listTabs: {
|
||||
empty: '',
|
||||
all: 'lahat',
|
||||
top_result: 'nangungunang resulta',
|
||||
album: 'album | mga album',
|
||||
artist: 'artist | mga artist',
|
||||
single: 'single | mga single',
|
||||
title: 'pamagat | mga pamagat',
|
||||
track: 'track | mga track',
|
||||
trackN: '0 mga track | {n} track | {n} mga track',
|
||||
releaseN: '0 mga release | {n} release | {n} mga release',
|
||||
playlist: 'playlist | mga playlist',
|
||||
compile: 'pinagsama | mga pinagsama',
|
||||
ep: 'ep | mga ep',
|
||||
bundle: 'bundle | mga bundle',
|
||||
more: 'Iba pang mga album',
|
||||
featured: 'Ibinida sa',
|
||||
spotifyPlaylist: 'playlist sa spotify | mga playlist sa spotify',
|
||||
releaseDate: 'petsa ng paglabas',
|
||||
error: 'error'
|
||||
}
|
||||
},
|
||||
about: {
|
||||
updates: {
|
||||
currentVersion: 'Kasalukuyang version',
|
||||
versionNotAvailable: 'H/P',
|
||||
updateAvailable: `Hindi mo ginagamit ang pinakabagong version: {version}`,
|
||||
deemixVersion: 'deemix lib version'
|
||||
},
|
||||
titles: {
|
||||
usefulLinks: 'Nakatutulong na mga Link',
|
||||
bugReports: 'Report sa Bug',
|
||||
contributing: 'Pagtulong',
|
||||
donations: 'Mga donasiyon',
|
||||
license: 'Lisensiya'
|
||||
},
|
||||
subtitles: {
|
||||
bugReports: "Meron bang hindi gumagana sa deemix? Ipaalam mo sa amin!",
|
||||
contributing: 'Gusto mo bang tumulong sa proyektong ito? Pwede mong gawin iyan sa maraming paraan!',
|
||||
donations: 'Gusto mo bang tumulong sa pamamagitan ng pera? Pwede kang magbigay ng donasiyon!'
|
||||
},
|
||||
usesLibrary: 'Ang app na ito ay gumagamit ng library galing sa <strong>deemix</strong>, na kung saan ay pwede mong gamitin para gumawa ng sarili mong UI ng deemix.',
|
||||
thanks: `Salamat kay <strong>rtonno</strong>, <strong>uhwot</strong> at <strong>lollilol</strong> sa pagtulong sa akin para sa proyektong ito at kay <strong>BasCurtiz</strong> at <strong>scarvimane</strong> sa paggawa ng icon.`,
|
||||
upToDate: `Huwag magpapahuli sa mga update patungkol dito sa pamamagitan ng pagsali sa <a href="https://t.me/RemixDevNews" target="_blank">news channel</a> sa Telegram.`,
|
||||
officialWebsite: 'Opisyal na Website',
|
||||
officialRepo: 'Opisyal na Library Repository',
|
||||
officialWebuiRepo: 'Opisyal na Repository ng WebUI',
|
||||
officialSubreddit: 'Opisyal na Subreddit',
|
||||
newsChannel: 'News Channel',
|
||||
questions: `Kung may tanong ka o problema sa app, maghanap ka muna ng solusiyon sa <a href="https://www.reddit.com/r/deemix" target="_blank">subreddit</a>. Ngayon, kung wala ka talagang mahanap ay pwede kang mag-post patungkol sa iyong isyu doon sa subreddit.`,
|
||||
beforeReporting: `Bago ka magreport ng bug, siguraduhing pinakabagong version ang ginagamit mo at ang ire-report mo ay talagang bug at hindi dahil sa pagkakamali mo lang ng paggamit.`,
|
||||
beSure: `Siguraduhing nangyayari rin ang bug sa iba't ibang plataporma at tsaka <strong>HUWAG</strong> mo nang i-report ang bug kung ito ay naipa-alam na ng iba.`,
|
||||
duplicateReports: 'Isasara namin ang mga magkaparehong report sa bug, kaya alamin mo muna.',
|
||||
dontOpenIssues: `<strong>HUWAG</strong> kayong magbubukas ng isyu kung magtatanong lang kayo, meron tayong subreddit para diyan.`,
|
||||
newUI: `Kung ikaw ay maraming alam sa python, subukan mong gumawa ng bagong UI gamit ng base library, o kaya ayusin ang mga bug sa library sa pamamagitan ng pag-pull ng request sa <a href="https://codeberg.org/RemixDev/deemix" target="_blank">repo</a>.`,
|
||||
acceptFeatures: `Tumatangggap din ako ng mga feature, basta hindi komplikado, dahil diretso ko itong nilalagay sa app at hindi sa library.`,
|
||||
otherLanguages: `Kung ikaw ay maraming alam sa ibang programming language, maaari mo ring subukan i-port ang deemix sa iba't ibang programming language!`,
|
||||
understandingCode: `Kailangan mo ba ng tulong para maintindihan ang code? Bisitahin si RemixDev sa Telegram o sa Reddit.`,
|
||||
contributeWebUI: `Kung may alam ka sa Vue.js (JavaScript), HTML o kaya CSS, maaari kang sumali at tumulong dito sa <a href="https://codeberg.org/RemixDev/deemix-webui" target="_blank">WebUI</a>.`,
|
||||
itsFree: `Lagi mong tandaang <strong>ang proyektong ito ay libre</strong> at <strong>suportuhanmuna ang minamahal ninyong mga artist</strong> bago ang mga developer.`,
|
||||
notObligated: `Huwag mong pilitin ang sarili para mag-donate, Naiintindihan ka namin!`,
|
||||
lincensedUnder: `Ang aktibidad na ito ay lisensiyado sa
|
||||
<a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GNU General Public License 3.0</a>.`
|
||||
},
|
||||
charts: {
|
||||
title: 'Mga Chart',
|
||||
changeCountry: 'Palitan ang Country',
|
||||
download: 'I-download ang Chart'
|
||||
},
|
||||
errors: {
|
||||
title: 'Mga error sa {name}',
|
||||
ids: {
|
||||
invalidURL: 'Hindi makilala ang URL',
|
||||
unsupportedURL: 'Hindi pa suportado ang URL',
|
||||
ISRCnotOnDeezer: 'Ang Track ISRC ay hindi pwede sa Deezer',
|
||||
notYourPrivatePlaylist: "Hindi pwedeng i-download ang mga pribadong playlist ng iba.",
|
||||
spotifyDisabled: 'Hindi mo nai-set nang tama ang Spotify Features.',
|
||||
trackNotOnDeezer: 'Hindi mahanap ang track sa Deezer!',
|
||||
albumNotOnDeezer: 'Hindi mahanap ang album sa Deezer!',
|
||||
notOnDeezer: 'Hindi available ang track sa Deezer!',
|
||||
notEncoded: 'Hindi pa nae-encode ang track!',
|
||||
notEncodedNoAlternative: 'Hindi pa nae-encode ang track at walang mahanap na iba!',
|
||||
wrongBitrate: 'Hindi mahanap ang track sa gusto mong bitrate.',
|
||||
wrongBitrateNoAlternative: 'Hindi mahanap ang track sa gusto mong bitrate at walang mahanap na iba!',
|
||||
no360RA: 'Hindi pwede ang track para sa Reality Audio 360.',
|
||||
notAvailable: "Walang available na track sa server ng Deezer!",
|
||||
notAvailableNoAlternative: "Walang available na track sa server ng Deezer at walang mahanap na iba!",
|
||||
noSpaceLeft: "Wala nang natitirang space sa iyong device!"
|
||||
}
|
||||
},
|
||||
favorites: {
|
||||
title: 'Mga Paborito',
|
||||
noPlaylists: 'Walang makitang mga Playlist',
|
||||
noAlbums: 'Walang makitang mga Paboritong Album',
|
||||
noArtists: 'Walang makitang mga Paboritong Artist',
|
||||
noTracks: 'Walang makitang mga Paboritong Track'
|
||||
},
|
||||
home: {
|
||||
needTologin: 'Kailangan mong mag-log in sa iyong Deezer account bago ka makasimulang magdownload.',
|
||||
openSettings: 'Buksan ang Mga Setting',
|
||||
sections: {
|
||||
popularPlaylists: 'Mga sikat na playlist',
|
||||
popularAlbums: 'Pinakamaraming pinakikinggang mga album'
|
||||
}
|
||||
},
|
||||
linkAnalyzer: {
|
||||
info: 'Pwede gamitin ang section na ito para sa iba pang impormasyon patungkol sa link na gusto mong i-download.',
|
||||
useful: "Makatutulong ito kung meron kang gustong i-download na track na hindi available sa bansa mo at gusto mong malaman kung meron bang ganito kapag sa iba.",
|
||||
linkNotSupported: 'Hindi pa suportado ang link',
|
||||
linkNotSupportedYet: 'Mukhang hindi pa suportado itong link, iba na lang ang ilagay mo.',
|
||||
table: {
|
||||
id: 'ID',
|
||||
isrc: 'ISRC',
|
||||
upc: 'UPC',
|
||||
duration: 'Haba',
|
||||
diskNumber: 'Bilang ng Disk',
|
||||
trackNumber: 'Bilang ng Track',
|
||||
releaseDate: 'Petsa ng Release',
|
||||
bpm: 'BPM',
|
||||
label: 'Label',
|
||||
recordType: 'Uri ng Rekord',
|
||||
genres: 'Mga Genre',
|
||||
tracklist: 'Listahan ng Track'
|
||||
}
|
||||
},
|
||||
search: {
|
||||
startSearching: 'Simulang Maghanap!',
|
||||
description: 'Pwede kang maghanap ng track, buong album, artist, playlist.... kahit ano! Pwede ka ring mag-paste dito ng link na galing sa Deezer',
|
||||
fans: '{n} mga fan',
|
||||
noResults: 'Walang resulta',
|
||||
noResultsTrack: 'Walang mahanap na mga Track',
|
||||
noResultsAlbum: 'Walang mahanap na mga Album',
|
||||
noResultsArtist: 'Walang mahanap na mga Artist',
|
||||
noResultsPlaylist: 'Walang mahanap na mga Playlist'
|
||||
},
|
||||
searchbar: 'Maghanap ka ng gusto mo (o mag-paste ka ng link)',
|
||||
downloads: 'mga download',
|
||||
toasts: {
|
||||
restoringQueue: 'Binabalik ang download queue...',
|
||||
queueRestored: 'Naibalik na ang download queue!',
|
||||
addedToQueue: '{item} ay naidagdag sa queue',
|
||||
addedMoreToQueue: '{n} naidagdag rin sa queue',
|
||||
alreadyInQueue: '{item} ay meron na sa queue!',
|
||||
finishDownload: '{item} ay natapos nang i-download.',
|
||||
allDownloaded: 'Nadownload na lahat!',
|
||||
refreshFavs: 'Narefresh na!',
|
||||
loggingIn: 'Nagla-log in...',
|
||||
loggedIn: 'Na-login na',
|
||||
alreadyLogged: 'Nakalogin ka na',
|
||||
loginFailed: "Hindi maka-log in",
|
||||
loggedOut: 'Na-logout na',
|
||||
cancellingCurrentItem: 'Kinakansel ang item.',
|
||||
currentItemCancelled: 'Nakansel na ang item.',
|
||||
startAddingArtist: 'Idinadagdag si {artist} sa queue ng mga album',
|
||||
finishAddingArtist: 'Naidagdag na si {artist} sa queue ng mga album',
|
||||
startConvertingSpotifyPlaylist: 'Kino-convert ang mga track sa spotify papuntang Deezer',
|
||||
finishConvertingSpotifyPlaylist: 'Naconvert na ang playlist sa Spotify',
|
||||
loginNeededToDownload: 'Kailangan mong mag-login para madownload ang mga track!',
|
||||
deezerNotAvailable: 'Hindi available ang Deezer sa iyong bansa. Kailangan mong gumamit ng VPN.'
|
||||
},
|
||||
settings: {
|
||||
title: 'Mga Setting',
|
||||
languages: 'Mga Wika',
|
||||
login: {
|
||||
title: 'Login',
|
||||
loggedIn: 'Ikaw ay naka-login sa pangalang {username}',
|
||||
arl: {
|
||||
question: 'Paano ako makakuha ng sariling ARL?',
|
||||
update: 'I-update ang ARL'
|
||||
},
|
||||
logout: 'Logout',
|
||||
login: 'Mag-login gamit ng deezer.com'
|
||||
},
|
||||
appearance: {
|
||||
title: 'Hitsura',
|
||||
slimDownloadTab: 'Pinaliit na download tab'
|
||||
},
|
||||
downloadPath: {
|
||||
title: 'Paglalagyan ng Download'
|
||||
},
|
||||
templates: {
|
||||
title: 'Mga Template',
|
||||
tracknameTemplate: 'Template sa pangalan ng Track',
|
||||
albumTracknameTemplate: 'Template sa track ng Album',
|
||||
playlistTracknameTemplate: 'Template sa track ng Playlist'
|
||||
},
|
||||
folders: {
|
||||
title: 'Mga Folder',
|
||||
createPlaylistFolder: 'Gumawa ng folder para sa mga playlist',
|
||||
playlistNameTemplate: 'Template sa folder ng Playlist',
|
||||
createArtistFolder: 'Gumawa ng folder para sa artist',
|
||||
artistNameTemplate: 'Template sa folder ng Artist',
|
||||
createAlbumFolder: 'Gumawa ng folder para sa album',
|
||||
albumNameTemplate: 'Template sa folder ng Album',
|
||||
createCDFolder: 'Gumawa ng folder para sa mga CD',
|
||||
createStructurePlaylist: 'Gumawa ng istraktura ng folder para sa mga playlist',
|
||||
createSingleFolder: 'Gumawa ng istraktura ng folder para sa mga single'
|
||||
},
|
||||
trackTitles: {
|
||||
title: 'Pamagat sa mga track',
|
||||
padTracks: 'Mga track ng Pad',
|
||||
paddingSize: 'Patungan ang laki ng padding',
|
||||
illegalCharacterReplacer: 'Pamalit sa ilegal na Karakter'
|
||||
},
|
||||
downloads: {
|
||||
title: 'Mga Download',
|
||||
queueConcurrency: 'Mga Kasabay na Download',
|
||||
maxBitrate: {
|
||||
title: 'Gustong Bitrate',
|
||||
9: 'FLAC 1411kbps',
|
||||
3: 'MP3 320kbps',
|
||||
1: 'MP3 128kbps'
|
||||
},
|
||||
overwriteFile: {
|
||||
title: 'Papatungan ko ba ang file?',
|
||||
y: 'Oo, patungan mo ang file',
|
||||
n: "Hindi, huwag mong patungan ang file",
|
||||
t: 'Patungan mo lang ang mga tag',
|
||||
b: 'Hindi, hayaan mo silang dalawa at lagyan mo lang ng numero sa kapareho niya',
|
||||
e: "Hindi, at huwag mong tignan ang mga extension"
|
||||
},
|
||||
fallbackBitrate: 'Binabaang bitrate',
|
||||
fallbackSearch: 'Maghanap para sa binabaan',
|
||||
logErrors: 'Gumawa ng log file para sa mga error',
|
||||
logSearched: 'Gumawa ng log file para sa mga hinanap na track',
|
||||
createM3U8File: 'Gumawa ng file sa playlist',
|
||||
syncedLyrics: 'Gumawa ng mga .lyr file (Mga Sync Lyric)',
|
||||
playlistFilenameTemplate: 'Template sa pangalan ng Playlist file',
|
||||
saveDownloadQueue: 'I-save ang download queue kapag isasara the app'
|
||||
},
|
||||
covers: {
|
||||
title: 'Mga cover ng album',
|
||||
saveArtwork: 'I-save ang mga Cover',
|
||||
coverImageTemplate: 'Template ng pangalan ng cover',
|
||||
saveArtworkArtist: 'I-save ang imahe ng artist',
|
||||
artistImageTemplate: 'Template ng imahe ng artist',
|
||||
localArtworkSize: 'Laki ng lokal na artwork',
|
||||
embeddedArtworkSize: 'Laki ng Nakadikit na artwork',
|
||||
localArtworkFormat: {
|
||||
title: 'Anong gusto mong format para sa mga lokal na artwork?',
|
||||
jpg: 'jpeg na imahe',
|
||||
png: 'png na imahe',
|
||||
both: 'Parehong jpeg at png'
|
||||
},
|
||||
jpegImageQuality: 'Kalidad ng JPEG na imahe',
|
||||
embeddedArtworkPNG: 'I-save ang nakadikit na artwork bilang PNG',
|
||||
embeddedPNGWarning: 'Ang mga PNG ay hindi opisyal na suportado ng Deezer at maaaring magkaroon ng bug',
|
||||
imageSizeWarning: 'Lahat ng mas mataas sa x1200 ay hindi opisyal na ginagamit sa Deezer, at posibleng magkaroon ng isyu',
|
||||
coverDescriptionUTF8: 'I-save ang deskripsyon ng cover gamit ng UTF8 (iTunes Cover Fix)'
|
||||
},
|
||||
tags: {
|
||||
head: 'Aling tag ang ise-save',
|
||||
title: 'Pamagat',
|
||||
artist: 'Artist',
|
||||
album: 'Album',
|
||||
cover: 'Cover',
|
||||
trackNumber: 'Bilang ng Track',
|
||||
trackTotal: 'Kabuuang Track',
|
||||
discNumber: 'Bilang ng Disk',
|
||||
discTotal: 'Kabuuang Disk',
|
||||
albumArtist: 'Album Artist',
|
||||
genre: 'Genre',
|
||||
year: 'Taon',
|
||||
date: 'Petsa',
|
||||
explicit: 'Mga Explicit na Lyric',
|
||||
isrc: 'ISRC',
|
||||
length: 'Haba ng Track',
|
||||
barcode: 'Barcode ng Album (UPC)',
|
||||
bpm: 'BPM',
|
||||
replayGain: 'Replay Gain',
|
||||
label: 'Label ng Album',
|
||||
lyrics: 'Unsynchronized na mga Lyric',
|
||||
syncedLyrics: 'Synchronized na mga Lyric',
|
||||
copyright: 'Karapatang Ari',
|
||||
composer: 'Komposer',
|
||||
involvedPeople: 'Mga Kasamang Tao'
|
||||
},
|
||||
other: {
|
||||
title: 'Iba pa',
|
||||
savePlaylistAsCompilation: 'I-save ang mga playlist bilang compilation',
|
||||
useNullSeparator: 'Gumamit ng panghiwalay sa null',
|
||||
saveID3v1: 'I-save rin ang ID3v1',
|
||||
multiArtistSeparator: {
|
||||
title: 'Anong gusto mo para maihanay mga artist?',
|
||||
nothing: 'I-save lang ang pangunahing artist',
|
||||
default: 'Gamit ng standard na specification',
|
||||
andFeat: 'Gamit ng & at feat.',
|
||||
using: 'Gamit ng "{separator}"'
|
||||
},
|
||||
singleAlbumArtist: 'I-save lang ang pangunahing album ng artist',
|
||||
albumVariousArtists: 'Isama ang "Various Artists" sa mga Album Artist',
|
||||
removeAlbumVersion: 'Tanggalin ang "Album Version" sa pamagat ng track',
|
||||
removeDuplicateArtists: 'Tanggalin ang kombinasyon ng mga artist',
|
||||
dateFormat: {
|
||||
title: 'Format ng petsa para sa mga FLAC file',
|
||||
year: 'YYYY',
|
||||
month: 'MM',
|
||||
day: 'DD'
|
||||
},
|
||||
featuredToTitle: {
|
||||
title: 'Anong gagawin ko sa mga itinampok na artist',
|
||||
0: 'Wala',
|
||||
1: 'Tanggalin mo sila sa Pamagat',
|
||||
3: 'Tanggalin mo sila sa Pamagat mismo at Pamagat ng Album',
|
||||
2: 'Ilipat mo sila sa pamagat'
|
||||
},
|
||||
titleCasing: 'Pagleletra sa Pamagat',
|
||||
artistCasing: 'Pagleletra sa Artist',
|
||||
casing: {
|
||||
nothing: 'Walang babaguhin',
|
||||
lower: 'maliliit',
|
||||
upper: 'MALALAKI',
|
||||
start: 'Simula Ng Bawata Salita',
|
||||
sentence: 'Kagaya ng pangungusap'
|
||||
},
|
||||
previewVolume: 'Volume ng Preview',
|
||||
executeCommand: {
|
||||
title: 'Mga gagawin pagkatapos ng download',
|
||||
description: 'Hayaan lang na blangko kung wala'
|
||||
}
|
||||
},
|
||||
spotify: {
|
||||
title: 'Spotify Features',
|
||||
clientID: 'Spotify ClientID',
|
||||
clientSecret: 'Spotify Client Secret',
|
||||
username: 'Spotify Username',
|
||||
question: 'Paano ma-enable ang Spotify Features?'
|
||||
},
|
||||
reset: 'Ibalik sa Dati',
|
||||
save: 'I-save',
|
||||
toasts: {
|
||||
init: 'Ikinarga ang mga Setting!',
|
||||
update: 'In-update ang mga Setting!',
|
||||
ARLcopied: 'Kinopya ang ARL sa clipboard'
|
||||
}
|
||||
},
|
||||
sidebar: {
|
||||
home: 'tahanan',
|
||||
search: 'maghanap',
|
||||
charts: 'mga chart',
|
||||
favorites: 'mga paborito',
|
||||
linkAnalyzer: 'tagasuri ng link',
|
||||
settings: 'mga setting',
|
||||
about: 'tungkol sa'
|
||||
},
|
||||
tracklist: {
|
||||
downloadSelection: 'Pagpipili ng download'
|
||||
}
|
||||
}
|
||||
|
||||
export default ph
|
@ -39,11 +39,12 @@
|
||||
license: 'Licença'
|
||||
},
|
||||
subtitles: {
|
||||
bugReports: "Há algo não funcionando no deemix? Nos diga!",
|
||||
bugReports: 'Há algo não funcionando no deemix? Nos diga!',
|
||||
contributing: 'Você quer contribuir para este projeto? Você pode fazer isso de diferentes maneiras!',
|
||||
donations: 'Você quer contribuir monetariamente? Você pode fazer uma doação!'
|
||||
},
|
||||
usesLibrary: 'Esse app usa a biblioteca do <strong>deemix</strong>, no qual você pode usar para criar sua própria UI para o deemix',
|
||||
usesLibrary:
|
||||
'Esse app usa a biblioteca do <strong>deemix</strong>, no qual você pode usar para criar sua própria UI para o deemix',
|
||||
thanks: `Agradecimentos para <strong>rtonno</strong>, <strong>uhwot</strong> e <strong>lollilol</strong> por ajudar neste projeto, e para <strong>BasCurtiz</strong> e <strong>scarvimane</strong> por fazerem o ícone`,
|
||||
upToDate: `Para mais novidades siga o <a href="https://t.me/RemixDevNews" target="_blank">news channel</a> no Telegram.`,
|
||||
officialWebsite: 'Site Oficial',
|
||||
@ -79,7 +80,7 @@
|
||||
invalidURL: 'URL inválida',
|
||||
unsupportedURL: 'URL não suportada ainda',
|
||||
ISRCnotOnDeezer: 'Faixa ISRC não está disponível ainda no deezer',
|
||||
notYourPrivatePlaylist: "Você não pode baixar playlists privadas.",
|
||||
notYourPrivatePlaylist: 'Você não pode baixar playlists privadas.',
|
||||
spotifyDisabled: 'Os Recursos do Spotify não foram configurados corretamente.',
|
||||
trackNotOnDeezer: 'Faixa não encontrada no deezer!',
|
||||
albumNotOnDeezer: 'Album not found on deezer! Álbum não encontrado no deezer!',
|
||||
@ -89,8 +90,8 @@
|
||||
wrongBitrate: 'Faixa não encontrada no bitrate desejado.',
|
||||
wrongBitrateNoAlternative: 'Faixa não encontrada no bitrate desejado e nenhuma outra alternativa encontrada!',
|
||||
no360RA: 'Faixa não disponível na qualidade Reality Audio 360.',
|
||||
notAvailable: "Faixa não disponível nos servidores do deezer!",
|
||||
notAvailableNoAlternative: "Faixa não disponível nos servidores do deezer e nenhuma outra alternativa encontrada!"
|
||||
notAvailable: 'Faixa não disponível nos servidores do deezer!',
|
||||
notAvailableNoAlternative: 'Faixa não disponível nos servidores do deezer e nenhuma outra alternativa encontrada!'
|
||||
}
|
||||
},
|
||||
favorites: {
|
||||
@ -111,7 +112,7 @@
|
||||
linkAnalyzer: {
|
||||
info: 'Você pode usar essa seção para encontrar mais informações sobre o link que você quer baixar.',
|
||||
useful:
|
||||
"Isso é útil se você está tentando baixar algumas faixas que não estão disponíveis no seu país, e quer saber onde elas estão disponíveis, por exemplo.",
|
||||
'Isso é útil se você está tentando baixar algumas faixas que não estão disponíveis no seu país, e quer saber onde elas estão disponíveis, por exemplo.',
|
||||
linkNotSupported: 'Esse link não é suportado ainda',
|
||||
linkNotSupportedYet: 'Parece que esse link não é suportado ainda, tente analizar outro.',
|
||||
table: {
|
||||
@ -151,7 +152,7 @@
|
||||
loggingIn: 'Logando',
|
||||
loggedIn: 'Logado',
|
||||
alreadyLogged: 'Você já está logado',
|
||||
loginFailed: "Não foi possivel entrar",
|
||||
loginFailed: 'Não foi possivel entrar',
|
||||
loggedOut: 'Desconectando',
|
||||
cancellingCurrentItem: 'Cancelando item atual.',
|
||||
currentItemCancelled: 'Item atual cancelado.',
|
||||
@ -215,7 +216,7 @@
|
||||
overwriteFile: {
|
||||
title: 'Sobrescrever arquivos?',
|
||||
y: 'Sim, sobrescrever arquivos',
|
||||
n: "Não, não sobrescrever arquivos",
|
||||
n: 'Não, não sobrescrever arquivos',
|
||||
t: 'Sobrescrever apenas as tags'
|
||||
},
|
||||
fallbackBitrate: 'Taxa de bits reserva',
|
||||
|
@ -1,54 +1,24 @@
|
||||
import Vue from 'vue'
|
||||
import VueI18n from 'vue-i18n'
|
||||
|
||||
// Languages
|
||||
import it from '@/lang/it'
|
||||
import en from '@/lang/en'
|
||||
import es from '@/lang/es'
|
||||
import de from '@/lang/de'
|
||||
import fr from '@/lang/fr'
|
||||
import id from '@/lang/id'
|
||||
import pt from '@/lang/pt-pt'
|
||||
import pt_br from '@/lang/pt-br'
|
||||
import ru from '@/lang/ru'
|
||||
import tr from '@/lang/tr'
|
||||
import vn from '@/lang/vn'
|
||||
import hr from '@/lang/hr'
|
||||
import ar from '@/lang/ar'
|
||||
import ko from '@/lang/ko'
|
||||
import { locales } from '@/lang/index'
|
||||
|
||||
Vue.use(VueI18n)
|
||||
|
||||
const DEFAULT_LANG = 'en'
|
||||
const storedLocale = localStorage.getItem('locale')
|
||||
const DEFAULT_LANG = storedLocale || 'en'
|
||||
|
||||
document.querySelector('html').setAttribute('lang', DEFAULT_LANG)
|
||||
|
||||
const locales = {
|
||||
it,
|
||||
en,
|
||||
es,
|
||||
de,
|
||||
fr,
|
||||
id,
|
||||
pt,
|
||||
pt_br,
|
||||
ru,
|
||||
tr,
|
||||
vn,
|
||||
hr,
|
||||
ar,
|
||||
ko
|
||||
}
|
||||
|
||||
const i18n = new VueI18n({
|
||||
locale: DEFAULT_LANG,
|
||||
fallbackLocale: DEFAULT_LANG,
|
||||
fallbackLocale: 'en',
|
||||
messages: locales,
|
||||
pluralizationRules: {
|
||||
/**
|
||||
* @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
|
||||
* @param choicesLength {number} an overall amount of available choices
|
||||
* @returns a final choice index to select plural word by
|
||||
* @param {number} choice A choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
|
||||
* @param {number} choicesLength An overall amount of available choices
|
||||
* @returns A final choice index to select plural word by
|
||||
*/
|
||||
ru: function(choice, choicesLength) {
|
||||
var n = Math.abs(choice) % 100
|
||||
|
@ -3,17 +3,17 @@ import VueRouter from 'vue-router'
|
||||
import { socket } from '@/utils/socket'
|
||||
import EventBus from '@/utils/EventBus'
|
||||
|
||||
import ArtistTab from '@components/ArtistTab.vue'
|
||||
import TracklistTab from '@components/TracklistTab.vue'
|
||||
|
||||
import TheHomeTab from '@components/TheHomeTab.vue'
|
||||
import TheChartsTab from '@components/TheChartsTab.vue'
|
||||
import TheFavoritesTab from '@components/TheFavoritesTab.vue'
|
||||
import TheErrorsTab from '@components/TheErrorsTab.vue'
|
||||
import TheLinkAnalyzerTab from '@components/TheLinkAnalyzerTab.vue'
|
||||
import TheAboutTab from '@components/TheAboutTab.vue'
|
||||
import TheSettingsTab from '@components/TheSettingsTab.vue'
|
||||
import TheMainSearch from '@components/TheMainSearch.vue'
|
||||
// Pages
|
||||
import About from '@components/pages/About.vue'
|
||||
import Artist from '@components/pages/Artist.vue'
|
||||
import Charts from '@components/pages/Charts.vue'
|
||||
import Errors from '@components/pages/Errors.vue'
|
||||
import Favorites from '@components/pages/Favorites.vue'
|
||||
import Home from '@components/pages/Home.vue'
|
||||
import LinkAnalyzer from '@components/pages/LinkAnalyzer.vue'
|
||||
import Search from '@components/pages/Search.vue'
|
||||
import Settings from '@components/pages/Settings.vue'
|
||||
import Tracklist from '@components/pages/Tracklist.vue'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
@ -21,7 +21,7 @@ const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: TheHomeTab,
|
||||
component: Home,
|
||||
meta: {
|
||||
notKeepAlive: true
|
||||
}
|
||||
@ -29,17 +29,32 @@ const routes = [
|
||||
{
|
||||
path: '/tracklist/:type/:id',
|
||||
name: 'Tracklist',
|
||||
component: TracklistTab
|
||||
component: Tracklist
|
||||
},
|
||||
{
|
||||
path: '/artist/:id',
|
||||
name: 'Artist',
|
||||
component: ArtistTab
|
||||
component: Artist
|
||||
},
|
||||
{
|
||||
path: '/album/:id',
|
||||
name: 'Album',
|
||||
component: Tracklist
|
||||
},
|
||||
{
|
||||
path: '/tracklist/:id',
|
||||
name: 'Playlist',
|
||||
component: Tracklist
|
||||
},
|
||||
{
|
||||
path: '/tracklist/:id',
|
||||
name: 'Spotify Playlist',
|
||||
component: Tracklist
|
||||
},
|
||||
{
|
||||
path: '/charts',
|
||||
name: 'Charts',
|
||||
component: TheChartsTab,
|
||||
component: Charts,
|
||||
meta: {
|
||||
notKeepAlive: true
|
||||
}
|
||||
@ -47,7 +62,7 @@ const routes = [
|
||||
{
|
||||
path: '/favorites',
|
||||
name: 'Favorites',
|
||||
component: TheFavoritesTab,
|
||||
component: Favorites,
|
||||
meta: {
|
||||
notKeepAlive: true
|
||||
}
|
||||
@ -55,32 +70,32 @@ const routes = [
|
||||
{
|
||||
path: '/errors',
|
||||
name: 'Errors',
|
||||
component: TheErrorsTab
|
||||
component: Errors
|
||||
},
|
||||
{
|
||||
path: '/link-analyzer',
|
||||
name: 'Link Analyzer',
|
||||
component: TheLinkAnalyzerTab
|
||||
component: LinkAnalyzer
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
component: TheAboutTab
|
||||
component: About
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
name: 'Settings',
|
||||
component: TheSettingsTab
|
||||
component: Settings
|
||||
},
|
||||
{
|
||||
path: '/search',
|
||||
name: 'Search',
|
||||
component: TheMainSearch
|
||||
component: Search
|
||||
},
|
||||
// 404 client side
|
||||
{
|
||||
path: '*',
|
||||
component: TheHomeTab
|
||||
component: Home
|
||||
}
|
||||
]
|
||||
|
||||
@ -109,6 +124,24 @@ router.beforeEach((to, from, next) => {
|
||||
id: to.params.id
|
||||
}
|
||||
break
|
||||
case 'Album':
|
||||
getTracklistParams = {
|
||||
type: 'album',
|
||||
id: to.params.id
|
||||
}
|
||||
break
|
||||
case 'Playlist':
|
||||
getTracklistParams = {
|
||||
type: 'playlist',
|
||||
id: to.params.id
|
||||
}
|
||||
break
|
||||
case 'Spotify Playlist':
|
||||
getTracklistParams = {
|
||||
type: 'spotifyplaylist',
|
||||
id: to.params.id
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
|
@ -72,7 +72,9 @@ const mutations = {
|
||||
},
|
||||
RESET_LOGIN(state) {
|
||||
// Needed for reactivity
|
||||
let clientMode = state.clientMode
|
||||
Object.assign(state, getDefaultState())
|
||||
state.clientMode = clientMode
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,58 +1,9 @@
|
||||
/* Center section */
|
||||
$icon-dimension: 2rem;
|
||||
$searchbar-height: calc(2rem + 1em);
|
||||
|
||||
#search {
|
||||
background-color: var(--secondary-background);
|
||||
width: 100%;
|
||||
padding: 0 1em;
|
||||
margin-bottom: 20px;
|
||||
margin-right: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid transparent;
|
||||
transition: border 200ms ease-in-out;
|
||||
|
||||
.search__icon {
|
||||
width: $icon-dimension;
|
||||
height: $icon-dimension;
|
||||
|
||||
i {
|
||||
font-size: $icon-dimension;
|
||||
color: var(--foreground);
|
||||
|
||||
@include remove-selection-background;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
border: 1px solid var(--foreground);
|
||||
}
|
||||
|
||||
#searchbar {
|
||||
height: $searchbar-height;
|
||||
padding-left: 0.5em;
|
||||
border: 0px;
|
||||
border-radius: 0px;
|
||||
background-color: var(--secondary-background);
|
||||
color: var(--foreground);
|
||||
font-size: 2rem;
|
||||
font-family: 'Open Sans';
|
||||
font-weight: 300;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// Removing Chrome autofill color
|
||||
&:-webkit-autofill,
|
||||
&:-webkit-autofill:hover,
|
||||
&:-webkit-autofill:focus,
|
||||
&:-webkit-autofill:active {
|
||||
-webkit-box-shadow: 0 0 0 $searchbar-height var(--secondary-background) inset !important;
|
||||
box-shadow: 0 0 0 $searchbar-height var(--secondary-background) inset !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#container {
|
||||
|
@ -20,6 +20,8 @@ $sidebar-delay: 75ms;
|
||||
|
||||
.main_tablinks {
|
||||
transition: all 500ms;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
|
||||
&.active {
|
||||
background-color: var(--accent-color);
|
||||
|
@ -295,14 +295,22 @@ a {
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
background-color: #000000;
|
||||
border-radius: 50%;
|
||||
min-width: 32px;
|
||||
padding: 0px;
|
||||
height: 44px;
|
||||
border: 0px;
|
||||
|
||||
i {
|
||||
background-color: #000000;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@ -312,6 +320,7 @@ a {
|
||||
|
||||
.download_overlay {
|
||||
opacity: 1;
|
||||
border: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ export async function adjustVolume(element, newVolume, { duration = 1000, easing
|
||||
return new Promise(resolve => {
|
||||
const timer = setInterval(() => {
|
||||
element.volume = originalVolume + easing(tick / ticks) * delta
|
||||
// console.log(element.volume)
|
||||
if (++tick === ticks) {
|
||||
clearInterval(timer)
|
||||
resolve()
|
||||
|
@ -1,19 +1,20 @@
|
||||
import it from 'svg-country-flags/svg/it.svg'
|
||||
import gb from 'svg-country-flags/svg/gb.svg'
|
||||
import es from 'svg-country-flags/svg/es.svg'
|
||||
import es from 'flag-icon-css/flags/4x3/es.svg'
|
||||
import de from 'svg-country-flags/svg/de.svg'
|
||||
import fr from 'svg-country-flags/svg/fr.svg'
|
||||
import id from 'svg-country-flags/svg/id.svg'
|
||||
import pt from 'svg-country-flags/svg/pt.svg'
|
||||
import pt from 'flag-icon-css/flags/4x3/pt.svg'
|
||||
import br from 'svg-country-flags/svg/br.svg'
|
||||
import ru from 'svg-country-flags/svg/ru.svg'
|
||||
import tr from 'svg-country-flags/svg/tr.svg'
|
||||
import vn from 'svg-country-flags/svg/vn.svg'
|
||||
import hr from 'svg-country-flags/svg/hr.svg'
|
||||
import hr from 'flag-icon-css/flags/4x3/hr.svg'
|
||||
import ar from '@/assets/ar.svg'
|
||||
import ko from 'svg-country-flags/svg/kr.svg'
|
||||
import ko from 'flag-icon-css/flags/4x3/kr.svg'
|
||||
import ph from 'flag-icon-css/flags/4x3/ph.svg'
|
||||
|
||||
export default {
|
||||
export const flags = {
|
||||
it,
|
||||
en: gb,
|
||||
es,
|
||||
@ -27,5 +28,6 @@ export default {
|
||||
vn,
|
||||
hr,
|
||||
ar,
|
||||
ko
|
||||
ko,
|
||||
ph
|
||||
}
|
||||
|
4
src/utils/texts.js
Normal file
4
src/utils/texts.js
Normal file
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* @param {string} text
|
||||
*/
|
||||
export const upperCaseFirstLowerCaseRest = text => text.charAt(0).toUpperCase() + text.slice(1).toLowerCase()
|
Loading…
Reference in New Issue
Block a user