Merge branch 'main' into 'igorruckert-main-patch-30619'
# Conflicts: # src/lang/pt-br.js
This commit is contained in:
commit
95b1833c97
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "deemix-webui",
|
||||
"version": "1.8.7",
|
||||
"version": "1.8.10",
|
||||
"scripts": {
|
||||
"clean": "rimraf public/js/bundle.js public/js/bundle.temp.js public/js/bundle.js.map",
|
||||
"clean-temp": "rimraf public/js/bundle.temp.js",
|
||||
|
File diff suppressed because one or more lines are too long
@ -26,8 +26,7 @@
|
||||
</i>
|
||||
<span
|
||||
:class="{ hidden: isSlim }"
|
||||
class="ml-5 overflow-hidden capitalize whitespace-no-wrap main-tablinks-text"
|
||||
style="letter-spacing: 1.3px"
|
||||
class="ml-3 overflow-hidden capitalize whitespace-no-wrap main-tablinks-text"
|
||||
>
|
||||
{{ $t(link.label) }}
|
||||
</span>
|
||||
|
@ -254,7 +254,7 @@ export default {
|
||||
},
|
||||
updateQueue(update) {
|
||||
// downloaded and failed default to false?
|
||||
const { uuid, downloaded, failed, progress, conversion, error, data, errid } = update
|
||||
const { uuid, downloaded, failed, progress, conversion, error, data, errid, stack } = update
|
||||
|
||||
if (uuid && this.queue.includes(uuid)) {
|
||||
if (downloaded) {
|
||||
@ -263,7 +263,7 @@ export default {
|
||||
|
||||
if (failed) {
|
||||
this.queueList[uuid].failed++
|
||||
this.queueList[uuid].errors.push({ message: error, data, errid })
|
||||
this.queueList[uuid].errors.push({ message: error, data, errid, stack })
|
||||
}
|
||||
|
||||
if (progress) {
|
||||
|
@ -26,7 +26,7 @@
|
||||
<li v-html="$t('about.thanks')"></li>
|
||||
<i18n path="about.upToDate.text" tag="li">
|
||||
<template #newsChannel>
|
||||
<a href="https://t.me/RemixDevNews" target="_blank">{{ $t('about.upToDate.newsChannel') }}</a>
|
||||
<a href="https://tg.deemix.app" target="_blank">{{ $t('about.upToDate.newsChannel') }}</a>
|
||||
</template>
|
||||
</i18n>
|
||||
</ul>
|
||||
@ -46,7 +46,10 @@
|
||||
<a href="https://www.reddit.com/r/deemix" target="_blank">🤖 {{ $t('about.officialSubreddit') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://t.me/RemixDevNews" target="_blank">📰 {{ $t('about.newsChannel') }}</a>
|
||||
<a href="https://tg.deemix.app" target="_blank">📰 {{ $t('about.newsChannel') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://t.me/RemixDevNews" target="_blank">💾 {{ $t('about.devlogChannel') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -118,10 +121,6 @@
|
||||
<strong>PayPal:</strong>
|
||||
<a href="https://paypal.me/RemixDev" target="_blank">PayPal.me/RemixDev</a>
|
||||
</li>
|
||||
<li>
|
||||
<i class="ethereum" v-html="ethereum" />
|
||||
<strong>Ethereum:</strong> 0x1d2aa67e671485CD4062289772B662e0A6Ff976c
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>{{ $t('about.titles.license') }}</h2>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<td>{{ error.data.id }}</td>
|
||||
<td>{{ error.data.artist }}</td>
|
||||
<td>{{ error.data.title }}</td>
|
||||
<td>{{ error.errid ? $t(`errors.ids.${error.errid}`) : error.message }}</td>
|
||||
<td><span :title="error.stack">{{ error.errid ? $t(`errors.ids.${error.errid}`) : error.message }}</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -24,10 +24,10 @@
|
||||
</button>
|
||||
|
||||
<div v-show="activeTab === 'playlist'">
|
||||
<div v-if="playlists.length === 0">
|
||||
<div v-if="(playlists.length + spotifyPlaylists.length) === 0">
|
||||
<h1>{{ $t('favorites.noPlaylists') }}</h1>
|
||||
</div>
|
||||
<div v-if="playlists.length > 0 || spotifyPlaylists.length > 0" class="release-grid">
|
||||
<div v-if="(playlists.length + spotifyPlaylists.length) > 0" class="release-grid">
|
||||
<div v-for="release in playlists" :key="release.id" class="release">
|
||||
<router-link :to="{ name: 'Playlist', params: { id: release.id } }" class="cursor-pointer" tag="div">
|
||||
<CoverContainer :cover="release.picture_medium" :link="release.link" is-rounded @click.stop="addToQueue" />
|
||||
@ -194,6 +194,7 @@ export default defineComponent({
|
||||
favoriteSpotifyPlaylists,
|
||||
favoritePlaylists,
|
||||
favoriteTracks,
|
||||
lovedTracksPlaylist,
|
||||
isRefreshingFavorites,
|
||||
refreshFavorites
|
||||
} = useFavorites()
|
||||
@ -217,6 +218,7 @@ export default defineComponent({
|
||||
artists: favoriteArtists,
|
||||
playlists: favoritePlaylists,
|
||||
spotifyPlaylists: favoriteSpotifyPlaylists,
|
||||
lovedTracks: lovedTracksPlaylist,
|
||||
refreshFavorites,
|
||||
isRefreshingFavorites
|
||||
}
|
||||
@ -236,9 +238,12 @@ export default defineComponent({
|
||||
const toDownload = this.getActiveRelease()
|
||||
|
||||
if (this.activeTab === 'track') {
|
||||
const lovedTracks = this.getLovedTracksPlaylist()
|
||||
|
||||
sendAddToQueue(lovedTracks.link)
|
||||
if (this.lovedTracks){
|
||||
sendAddToQueue(this.lovedTracks)
|
||||
} else {
|
||||
const lovedTracks = this.getLovedTracksPlaylist()
|
||||
sendAddToQueue(lovedTracks.link)
|
||||
}
|
||||
} else {
|
||||
sendAddToQueue(aggregateDownloadLinks(toDownload))
|
||||
}
|
||||
@ -255,6 +260,7 @@ export default defineComponent({
|
||||
switch (tab) {
|
||||
case 'playlist':
|
||||
toDownload = this.playlists
|
||||
toDownload += this.spotifyPlaylists
|
||||
break
|
||||
case 'album':
|
||||
toDownload = this.albums
|
||||
@ -289,6 +295,7 @@ export default defineComponent({
|
||||
if (lovedTracks.length !== 0) {
|
||||
return lovedTracks[0]
|
||||
} else {
|
||||
toast(this.$t('toasts.noLovedPlaylist'), 'warning', true)
|
||||
throw new Error('No loved tracks playlist!')
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@
|
||||
<h3>{{ $t('linkAnalyzer.countries') }}</h3>
|
||||
<p v-for="(country, i) in countries" :key="i">{{ country[0] }} - {{ country[1] }}</p>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-else-if="this.type === 'track'">
|
||||
<h3>{{ $t('linkAnalyzer.noCountries') }}</h3>
|
||||
</template>
|
||||
|
||||
|
@ -2,85 +2,78 @@
|
||||
<div class="fixed-footer">
|
||||
<h1 class="mb-8 text-5xl">{{ $t('settings.title') }}</h1>
|
||||
|
||||
<div v-if="isLoggedIn" id="logged_in_info" ref="loggedInInfo">
|
||||
<img
|
||||
id="settings_picture"
|
||||
ref="userpicture"
|
||||
:src="pictureHref"
|
||||
alt="Profile Picture"
|
||||
class="w-32 h-32 rounded-full"
|
||||
/>
|
||||
|
||||
<i18n path="settings.login.loggedIn" tag="p">
|
||||
<template #username>
|
||||
<strong id="settings_username" ref="username">{{ user.name || 'not logged' }}</strong>
|
||||
</template>
|
||||
</i18n>
|
||||
<p>{{userLicense}} | {{user.country}}</p>
|
||||
|
||||
<button class="btn btn-primary" @click="logout">
|
||||
{{ $t('settings.login.logout') }}
|
||||
</button>
|
||||
|
||||
<select v-if="accounts.length > 1" id="family_account" v-model="accountNum" @change="changeAccount">
|
||||
<option v-for="(account, i) in accounts" :key="account" :value="i.toString()">
|
||||
{{ account.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<h3 class="settings-group__header"><i class="material-icons">person</i>{{ $t('settings.login.title') }}</h3>
|
||||
|
||||
<div class="my-5 space-y-5">
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
id="login_input_arl"
|
||||
ref="loginInput"
|
||||
:value="arl"
|
||||
autocomplete="off"
|
||||
placeholder="ARL"
|
||||
type="password"
|
||||
/>
|
||||
<button class="ml-2 btn btn-primary btn-only-icon" @click="copyARLtoClipboard">
|
||||
<i class="material-icons">assignment</i>
|
||||
<div v-if="isLoggedIn" id="logged_in_info" ref="loggedInInfo">
|
||||
<img
|
||||
id="settings_picture"
|
||||
ref="userpicture"
|
||||
:src="pictureHref"
|
||||
alt="Profile Picture"
|
||||
class="w-32 h-32 rounded-full"
|
||||
/>
|
||||
<div class="user_info">
|
||||
<i18n path="settings.login.loggedIn" tag="p">
|
||||
<template #username>
|
||||
<strong id="settings_username" ref="username">{{ user.name || 'not logged' }}</strong>
|
||||
</template>
|
||||
</i18n>
|
||||
<p>{{userLicense}} | {{user.country}}</p>
|
||||
|
||||
<button class="btn btn-primary mt-3" @click="logout">
|
||||
{{ $t('settings.login.logout') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<RouterLink :to="{ name: 'ARL' }" class="block">
|
||||
{{ $t('settings.login.arl.question') }}
|
||||
</RouterLink>
|
||||
|
||||
<!--
|
||||
Uncomment when implemented
|
||||
<a v-if="clientMode" class="block" href="#" @click="appLogin">
|
||||
{{ $t('settings.login.login') }}
|
||||
</a>
|
||||
-->
|
||||
|
||||
<button class="btn btn-primary" style="width: 100%" @click="loginButton">
|
||||
{{ $t('settings.login.arl.update') }}
|
||||
</button>
|
||||
<select v-if="accounts.length > 1" id="family_account" v-model="accountNum" @change="changeAccount">
|
||||
<option v-for="(account, i) in accounts" :key="account" :value="i.toString()">
|
||||
{{ account.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!isLoggedIn" class="settings-group">
|
||||
<h3 class="settings-group__header">
|
||||
<i class="material-icons">person</i>{{ $t('settings.loginWithCredentials.title') }}
|
||||
</h3>
|
||||
<div v-else>
|
||||
<form ref="loginWithCredentialsForm" @submit.prevent="loginWithCredentials">
|
||||
<label>
|
||||
<span>{{ $t('settings.loginWithCredentials.email') }}</span>
|
||||
<input type="text" name="email" placeholder="email@example.com" class="mb-6"/>
|
||||
</label>
|
||||
<label>
|
||||
<span>{{ $t('settings.loginWithCredentials.password') }}</span>
|
||||
<input type="password" name="password" placeholder="●●●●●●●●" class="mb-6"/>
|
||||
</label>
|
||||
<button class="btn btn-primary login-button" type="submit">{{ $t('settings.loginWithCredentials.login') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form ref="loginWithCredentialsForm" class="my-5 space-y-5" @submit.prevent="loginWithCredentials">
|
||||
<label>
|
||||
<span>{{ $t('settings.loginWithCredentials.email') }}</span>
|
||||
<input type="text" name="email" />
|
||||
</label>
|
||||
<label>
|
||||
<span>{{ $t('settings.loginWithCredentials.password') }}</span>
|
||||
<input type="password" name="password" />
|
||||
</label>
|
||||
<BaseAccordion class="my-5 space-y-5">
|
||||
<template #title>
|
||||
<span>{{ $t('settings.login.arl.title') }}</span>
|
||||
</template>
|
||||
<div class="my-5 space-y-5">
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
id="login_input_arl"
|
||||
ref="loginInput"
|
||||
:value="arl"
|
||||
autocomplete="off"
|
||||
placeholder="ARL"
|
||||
type="password"
|
||||
/>
|
||||
<button class="ml-2 btn btn-primary btn-only-icon" @click="copyARLtoClipboard">
|
||||
<i class="material-icons">assignment</i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" type="submit">{{ $t('settings.loginWithCredentials.login') }}</button>
|
||||
</form>
|
||||
<RouterLink :to="{ name: 'ARL' }" class="block">
|
||||
{{ $t('settings.login.arl.question') }}
|
||||
</RouterLink>
|
||||
|
||||
<button class="btn btn-primary" style="width: 100%" @click="loginButton">
|
||||
{{ $t('settings.login.arl.update') }}
|
||||
</button>
|
||||
</div>
|
||||
</BaseAccordion>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
@ -364,6 +357,10 @@
|
||||
<input v-model="settings.tags.artist" type="checkbox" />
|
||||
<span class="checkbox-text">{{ $t('settings.tags.artist') }}</span>
|
||||
</label>
|
||||
<label class="with-checkbox" v-if="settings.tags.multiArtistSeparator != 'default'">
|
||||
<input v-model="settings.tags.artists" type="checkbox" />
|
||||
<span class="checkbox-text">{{ $t('settings.tags.artists') }}</span>
|
||||
</label>
|
||||
<label class="with-checkbox">
|
||||
<input v-model="settings.tags.album" type="checkbox" />
|
||||
<span class="checkbox-text">{{ $t('settings.tags.album') }}</span>
|
||||
@ -461,6 +458,9 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="settings.tags.multiArtistSeparator != 'default' && !settings.tags.artists" style="opacity: 0.75; color: #ffcc22">
|
||||
⚠️ {{ $t('settings.tags.artistsWarning') }}
|
||||
</p>
|
||||
</BaseAccordion>
|
||||
|
||||
<BaseAccordion class="settings-group">
|
||||
@ -506,6 +506,11 @@
|
||||
<input v-model="settings.fallbackSearch" type="checkbox" />
|
||||
<span class="checkbox-text">{{ $t('settings.downloads.fallbackSearch') }}</span>
|
||||
</label>
|
||||
|
||||
<label class="with-checkbox">
|
||||
<input v-model="settings.fallbackISRC" type="checkbox" />
|
||||
<span class="checkbox-text">{{ $t('settings.downloads.fallbackISRC') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-container__third settings-container__third--only-checkbox">
|
||||
<label class="with-checkbox">
|
||||
@ -517,6 +522,11 @@
|
||||
<input v-model="settings.logSearched" type="checkbox" />
|
||||
<span class="checkbox-text">{{ $t('settings.downloads.logSearched') }}</span>
|
||||
</label>
|
||||
|
||||
<label class="with-checkbox">
|
||||
<input v-model="settings.feelingLucky" type="checkbox" />
|
||||
<span class="checkbox-text">{{ $t('settings.downloads.feelingLucky') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-container__third settings-container__third--only-checkbox">
|
||||
<label class="with-checkbox">
|
||||
@ -579,6 +589,9 @@
|
||||
<option value=";">{{ $t('settings.other.multiArtistSeparator.using', { separator: ';' }) }}</option>
|
||||
<option value="; ">{{ $t('settings.other.multiArtistSeparator.using', { separator: '; ' }) }}</option>
|
||||
</select>
|
||||
<p v-if="settings.tags.multiArtistSeparator != 'default'" style="opacity: 0.75; color: #ffcc22">
|
||||
⚠️ {{ $t('settings.other.multiArtistSeparator.warning') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<label class="with-checkbox">
|
||||
@ -1007,6 +1020,10 @@ export default {
|
||||
const { email } = fromLoginForm('email')
|
||||
const { password } = fromLoginForm('password')
|
||||
|
||||
if (!email || !password) return
|
||||
|
||||
toast(this.$t('toasts.loggingIn'), 'loading', false, 'login-toast')
|
||||
|
||||
const { accessToken, arl } = await postToServer('loginWithCredentials', {
|
||||
email,
|
||||
password,
|
||||
@ -1015,6 +1032,7 @@ export default {
|
||||
|
||||
if (accessToken !== this.accessToken) this.dispatchAccessTocken({ accessToken })
|
||||
if (arl) this.login(arl)
|
||||
else toast(this.$t('toasts.loginFailed'), 'close', true, 'login-toast')
|
||||
},
|
||||
appLogin() {
|
||||
window.api.send('applogin')
|
||||
@ -1073,11 +1091,21 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#logged_in_info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
height: 250px;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
grid-template-columns: 128px auto;
|
||||
grid-template-rows: auto auto;
|
||||
}
|
||||
|
||||
#logged_in_info .user_info {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
#family_account {
|
||||
margin-top: 24px;
|
||||
grid-column: 1 / span 2;
|
||||
}
|
||||
|
||||
.locale-flag {
|
||||
@ -1164,4 +1192,12 @@ export default {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.login-button {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
</style>
|
||||
|
@ -11,6 +11,13 @@ const de = {
|
||||
toggle_download_tab_hint: 'Erweitern/Minimieren',
|
||||
clean_queue_hint: 'Vollständige entfernen',
|
||||
cancel_queue_hint: 'Alle abbrechen',
|
||||
open_downloads_folder: 'Download Ordner öffnen',
|
||||
cut: 'Ausschneiden',
|
||||
copy: 'Kopieren',
|
||||
copyLink: 'Link kopieren',
|
||||
copyImageLink: 'Bildlink kopieren',
|
||||
copyDeezerLink: 'Deezer Link kopieren',
|
||||
paste: 'Einfügen',
|
||||
listTabs: {
|
||||
empty: '',
|
||||
all: 'Alle',
|
||||
@ -28,7 +35,10 @@ const de = {
|
||||
spotifyPlaylist: 'Spotify Playlist | Spotify Playlists',
|
||||
releaseDate: 'Veröffentlichungsdatum',
|
||||
error: 'Fehler'
|
||||
}
|
||||
},
|
||||
yes: 'Ja',
|
||||
no: 'Nein',
|
||||
empty: 'Leer'
|
||||
},
|
||||
about: {
|
||||
appStatus: {
|
||||
@ -68,8 +78,7 @@ const de = {
|
||||
officialSubreddit: 'Offizieller Subreddit',
|
||||
newsChannel: 'Neuigkeiten Kanal',
|
||||
questions: {
|
||||
text:
|
||||
'Suche bei Fragen oder Problemen mit der App als erstes nach einer Lösung im {subreddit}. Wenn du dort nichts findest, kannst du einen Beitrag mit deinen Problem auf dem Subreddit verfassen.',
|
||||
text: 'Suche bei Fragen oder Problemen mit der App als erstes nach einer Lösung im {subreddit}. Wenn du dort nichts findest, kannst du einen Beitrag mit deinen Problem auf dem Subreddit verfassen.',
|
||||
subreddit: 'Subreddit'
|
||||
},
|
||||
beforeReporting:
|
||||
@ -80,8 +89,7 @@ const de = {
|
||||
dontOpenIssues:
|
||||
'<strong>ERSTELLE KEINE</strong> Fehlermeldungen um Fragen zu stellen, es existiert ein Subreddit dafür.',
|
||||
newUI: {
|
||||
text:
|
||||
'Wenn du Python fließend beherrschst, kannst du versuchen, mithilfe der Basisbibliothek eine neue Benutzeroberfläche für die App zu erstellen oder Fehler in der Bibliothek mit einem Pull-Request in der {repo} zu beheben.',
|
||||
text: 'Wenn du Python fließend beherrschst, kannst du versuchen, mithilfe der Basisbibliothek eine neue Benutzeroberfläche für die App zu erstellen oder Fehler in der Bibliothek mit einem Pull-Request in der {repo} zu beheben.',
|
||||
repo: 'deemix Repo'
|
||||
},
|
||||
acceptFeatures:
|
||||
@ -121,10 +129,13 @@ const de = {
|
||||
notEncodedNoAlternative: 'Track noch nicht codiert und keine Alternative gefunden!',
|
||||
wrongBitrate: 'Track mit gewünschter Bitrate nicht gefunden.',
|
||||
wrongBitrateNoAlternative: 'Track mit gewünschter Bitrate nicht gefunden und keine Alternative gefunden!',
|
||||
no360RA: 'Track ist nicht verfügbar in Reality Audio 360.',
|
||||
notAvailable: 'Track ist noch nicht verfügbar auf den Servern von Deezer!',
|
||||
notAvailableNoAlternative:
|
||||
'Track ist noch nicht verfügbar auf den Servern von Deezer und keine Alternativen gefunden!!'
|
||||
no360RA: 'Track ist nicht in Reality Audio 360 verfügbar.',
|
||||
notAvailable: 'Track ist nicht verfügbar auf den Servern von Deezer!',
|
||||
notAvailableNoAlternative: 'Track ist nicht auf den Servern von Deezer verfügbar, keine Alternativen gefunden!',
|
||||
noSpaceLeft: 'Kein Speicherplatz auf dem Gerät!',
|
||||
albumDoesntExists: 'Das Album des Tracks ist nicht vorhanden, konnte keine Informationen sammeln.',
|
||||
wrongLicense: 'Dein Account kann die Spur nicht an der gewünschten Bitrate streamen.',
|
||||
wrongGeolocation: 'Dein Account kann den Track nicht aus Deinem aktuellen Land streamen.'
|
||||
}
|
||||
},
|
||||
favorites: {
|
||||
@ -143,8 +154,7 @@ const de = {
|
||||
}
|
||||
},
|
||||
linkAnalyzer: {
|
||||
info:
|
||||
'Diesen Abschnitt kannst du nutzen, um weitere Informationen über den gewünschten Link zu erhalten, den du herunterladen möchtest.',
|
||||
info: 'Diesen Abschnitt kannst du nutzen, um weitere Informationen über den gewünschten Link zu erhalten, den du herunterladen möchtest.',
|
||||
useful:
|
||||
'Dies ist z.B. nützlich, wenn du versuchst einige Titel herunterzuladen, welche in deinem Land nicht verfügbar sind, und du wissen möchtest, wo sie verfügbar sind.',
|
||||
linkNotSupported: 'Dieser Link wird noch nicht unterstützt',
|
||||
@ -162,8 +172,12 @@ const de = {
|
||||
label: 'Label',
|
||||
recordType: 'Art der Aufnahme',
|
||||
genres: 'Genres',
|
||||
tracklist: 'Trackliste'
|
||||
}
|
||||
tracklist: 'Trackliste',
|
||||
readable: 'Lesbar',
|
||||
available: 'Verfügbar'
|
||||
},
|
||||
countries: 'Länder',
|
||||
noCountries: 'Dieser Track ist in keinem Land verfügbar.'
|
||||
},
|
||||
search: {
|
||||
startSearching: 'Suche starten!',
|
||||
@ -183,7 +197,7 @@ const de = {
|
||||
alreadyInQueue: '{item} ist bereits in der Warteschlange!',
|
||||
finishDownload: '{item} vollständig heruntergeladen.',
|
||||
allDownloaded: 'Alle Downloads abgeschlossen!',
|
||||
refreshFavs: 'Abgeschlossene Downloads neu laden!',
|
||||
refreshFavs: 'Abgeschlossene Downloads neuladen!',
|
||||
loggingIn: 'Einloggen',
|
||||
loggedIn: 'Eingeloggt',
|
||||
alreadyLogged: 'Bereits eingeloggt',
|
||||
@ -191,10 +205,14 @@ const de = {
|
||||
loggedOut: 'Ausgeloggt',
|
||||
cancellingCurrentItem: 'Aktuelle Auswahl abbrechen.',
|
||||
currentItemCancelled: 'Aktuelle Auswahl wurde abgebrochen',
|
||||
startAddingArtist: '{artist} Alben werden hinzugefügt',
|
||||
finishAddingArtist: '{artist} Alben wurden hinzugefügt',
|
||||
startAddingArtist: 'Alben von {artist} werden hinzugefügt',
|
||||
finishAddingArtist: 'Alben von {artist} wurden hinzugefügt',
|
||||
startConvertingSpotifyPlaylist: 'Konvertierern von Spotify-Tracks zu Deezer-Tracks',
|
||||
finishConvertingSpotifyPlaylist: 'Spotify Playlist convertiert'
|
||||
finishConvertingSpotifyPlaylist: 'Spotify Playlist convertiert',
|
||||
loginNeededToDownload: 'Du musst eingeloggt sein, um Tracks herunterladen zu können!',
|
||||
deezerNotAvailable: 'Deezer ist in deinem Land nicht verfügbar. Du solltest eine VPN nutzen.',
|
||||
startGeneratingItems: 'Verarbeite {n} Artikeln....',
|
||||
finishGeneratingItems: '{n} Items generiert.'
|
||||
},
|
||||
settings: {
|
||||
title: 'Einstellungen',
|
||||
@ -204,9 +222,10 @@ const de = {
|
||||
loggedIn: 'Du bist eingeloggt als {username}',
|
||||
arl: {
|
||||
question: 'Wie bekomme ich meine eigene ARL?',
|
||||
update: 'Update ARL'
|
||||
update: 'ARL aktualisieren'
|
||||
},
|
||||
logout: 'Ausloggen'
|
||||
logout: 'Ausloggen',
|
||||
login: 'Über deezer.com einloggen'
|
||||
},
|
||||
loginWithCredentials: {
|
||||
title: 'Mit Zugangsdaten einloggen',
|
||||
@ -216,7 +235,10 @@ const de = {
|
||||
},
|
||||
appearance: {
|
||||
title: 'Design',
|
||||
slimDownloadTab: 'Schmaler Download-Tab'
|
||||
slimDownloadTab: 'Schmaler Download-Tab',
|
||||
slimSidebar: 'Schlanke Seitenleiste',
|
||||
searchButton: 'Suchschaltfläche anzeigen',
|
||||
bitrateTags: 'Qualitäts-Tag in Download-Warteschlange anzeigen'
|
||||
},
|
||||
downloadPath: {
|
||||
title: 'Download Pfad'
|
||||
@ -224,8 +246,11 @@ const de = {
|
||||
templates: {
|
||||
title: 'Vorlagen',
|
||||
tracknameTemplate: 'Vorlage für den Tracknamen',
|
||||
albumTracknameTemplate: 'Vorlage für Tracks in einem Album',
|
||||
playlistTracknameTemplate: 'Vorlage für Tracks in einer Playlist'
|
||||
tracknameAvailableVariables: 'Verfügbare Trackname Variablen',
|
||||
albumTracknameTemplate: 'Album-Track-Vorlage.',
|
||||
albumTracknameAvailableVariables: 'Verfügbare Album-Track-Variablen',
|
||||
playlistTracknameTemplate: 'Vorlage für Tracks in einer Playlist',
|
||||
playlistTracknameAvailableVariables: 'Verfügbare Playlist Trackvariablen'
|
||||
},
|
||||
folders: {
|
||||
title: 'Ordner',
|
||||
@ -259,7 +284,8 @@ const de = {
|
||||
y: 'Ja überschreibe die Dateien',
|
||||
n: 'Nein überschreibe die Dateien nicht',
|
||||
t: 'Überschreibe nur die Tags',
|
||||
b: 'Nein, behalte beide Dateien und füge der Kopie eine Nummer hinzu'
|
||||
b: 'Nein, behalte beide Dateien und füge der Kopie eine Nummer hinzu',
|
||||
e: 'Nein, und schau nicht auf die Erweiterungen'
|
||||
},
|
||||
fallbackBitrate: 'Falls gewünschte Bitrate nicht verfügbar, auf niedrigere Bitrate zurückgreifen',
|
||||
fallbackSearch: 'Zur Suche zurückkehren, wenn der Song nicht verfügbar ist',
|
||||
@ -284,7 +310,11 @@ const de = {
|
||||
png: 'Ein png Bild',
|
||||
both: 'Beides (jpg + png)'
|
||||
},
|
||||
jpegImageQuality: 'JPEG Qualität'
|
||||
jpegImageQuality: 'JPEG Qualität',
|
||||
embeddedArtworkPNG: 'Eingebettete Grafiken als PNG speichern',
|
||||
embeddedPNGWarning: 'PNGs werden von Deezer nicht offiziell unterstützt und können fehlerhaft sein',
|
||||
imageSizeWarning: 'Alles über x1200 wird nicht offiziell von Deezer verwendet, es können Probleme auftreten',
|
||||
coverDescriptionUTF8: 'Cover-Beschreibung mit UTF8 speichern (iTunes Cover Fix)'
|
||||
},
|
||||
tags: {
|
||||
head: 'Welche Tags sollen gespeichert werden?',
|
||||
@ -308,9 +338,11 @@ const de = {
|
||||
replayGain: 'Wiedergabe Lautstärke',
|
||||
label: 'Album Plattenlabel',
|
||||
lyrics: 'Nicht synchronisierte Texte',
|
||||
syncedLyrics: 'Synchronisierte Texte',
|
||||
copyright: 'Copyright',
|
||||
composer: 'Komponist',
|
||||
involvedPeople: 'Mitwirkende Personen'
|
||||
involvedPeople: 'Mitwirkende Personen',
|
||||
source: 'Quelle und Song ID'
|
||||
},
|
||||
other: {
|
||||
title: 'Sonstige',
|
||||
@ -360,14 +392,21 @@ const de = {
|
||||
title: 'Spotify Features',
|
||||
clientID: 'Spotify Client ID',
|
||||
clientSecret: 'Spotify Client Secret',
|
||||
username: 'Spotify Benutzername'
|
||||
username: 'Spotify Benutzername',
|
||||
question: 'Wie aktiviere ich die Spotify Features?'
|
||||
},
|
||||
reset: 'Auf Standardwerte zurücksetzen',
|
||||
resetMessage: 'Bist du sicher, dass du zu den Standarteinstellungen zurückkehren willst?',
|
||||
save: 'Speichern',
|
||||
toasts: {
|
||||
init: 'Einstellungen geladen!',
|
||||
update: 'Einstellungen aktualisiert!',
|
||||
reset: 'Einstellungen auf den Standart zurückgesetzt!',
|
||||
ARLcopied: 'ARL wurde in die Zwischenablage kopiert'
|
||||
},
|
||||
logs: {
|
||||
title: 'Logs',
|
||||
areLogsActive: 'Aktiv'
|
||||
}
|
||||
},
|
||||
sidebar: {
|
||||
@ -380,7 +419,11 @@ const de = {
|
||||
about: 'Info'
|
||||
},
|
||||
tracklist: {
|
||||
downloadSelection: 'Downloads'
|
||||
downloadSelection: 'Herunterladen'
|
||||
},
|
||||
logs: {
|
||||
event: 'Event',
|
||||
data: 'Daten'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,7 @@ const en = {
|
||||
officialWebuiRepo: 'Official WebUI Repository',
|
||||
officialSubreddit: 'Official Subreddit',
|
||||
newsChannel: 'News Channel',
|
||||
devlogChannel: 'Devlog Channel',
|
||||
questions: {
|
||||
text: `If you have questions or problems with the app, search for a solution on the {subreddit} first. Then, if you don't find anything you can make a post with your issue on the subreddit.`,
|
||||
subreddit: 'subreddit'
|
||||
@ -133,7 +134,9 @@ const en = {
|
||||
noSpaceLeft: 'No space left on the device!',
|
||||
albumDoesntExists: "Track's album doesn't exist, failed to gather info.",
|
||||
wrongLicense: "Your account can't stream the track at the desired bitrate.",
|
||||
wrongGeolocation: "Your account can't stream the track from your current country."
|
||||
wrongGeolocation: "Your account can't stream the track from your current country.",
|
||||
wrongGeolocationNoAlternative:
|
||||
"Your account can't stream the track from your current country and no alternative found."
|
||||
}
|
||||
},
|
||||
favorites: {
|
||||
@ -212,7 +215,8 @@ const en = {
|
||||
loginNeededToDownload: 'You need to log in to download tracks!',
|
||||
deezerNotAvailable: 'Deezer is not available in your country. You should use a VPN.',
|
||||
startGeneratingItems: 'Processing {n} items...',
|
||||
finishGeneratingItems: 'Generated {n} items.'
|
||||
finishGeneratingItems: 'Generated {n} items.',
|
||||
noLovedPlaylist: 'No loved tracks playlist!'
|
||||
},
|
||||
settings: {
|
||||
title: 'Settings',
|
||||
@ -221,6 +225,7 @@ const en = {
|
||||
title: 'Login',
|
||||
loggedIn: 'You are logged in as {username}',
|
||||
arl: {
|
||||
title: 'Use ARL instead',
|
||||
question: 'How do I get my own ARL?',
|
||||
update: 'Update ARL'
|
||||
},
|
||||
@ -289,6 +294,8 @@ const en = {
|
||||
},
|
||||
fallbackBitrate: 'Bitrate fallback',
|
||||
fallbackSearch: 'Search fallback',
|
||||
fallbackISRC: 'Fallback with ISRC search',
|
||||
feelingLucky: 'Gamble with CDNs and caches',
|
||||
logErrors: 'Create log files for errors',
|
||||
logSearched: 'Create log files for searched tracks',
|
||||
createM3U8File: 'Create playlist file',
|
||||
@ -320,6 +327,7 @@ const en = {
|
||||
head: 'Which tags to save',
|
||||
title: 'Title',
|
||||
artist: 'Artist',
|
||||
artists: 'Extra ARTISTS tag',
|
||||
album: 'Album',
|
||||
cover: 'Cover',
|
||||
trackNumber: 'Track Number',
|
||||
@ -342,7 +350,9 @@ const en = {
|
||||
copyright: 'Copyright',
|
||||
composer: 'Composer',
|
||||
involvedPeople: 'Involved People',
|
||||
source: 'Source and song ID'
|
||||
source: 'Source and song ID',
|
||||
artistsWarning:
|
||||
"Disabling the ARTISTS tag while not using standard specification won't preserve multiartist support"
|
||||
},
|
||||
other: {
|
||||
title: 'Other',
|
||||
@ -354,7 +364,9 @@ const en = {
|
||||
nothing: 'Save only the main artist',
|
||||
default: 'Using standard specification',
|
||||
andFeat: 'Using & and feat.',
|
||||
using: 'Using "{separator}"'
|
||||
using: 'Using "{separator}"',
|
||||
warning:
|
||||
'Using any separator other than the standard specification will add a extra ARTISTS tag to preserve multiartist support'
|
||||
},
|
||||
singleAlbumArtist: 'Save only the main album artist',
|
||||
albumVariousArtists: 'Keep "Various Artists" in the Album Artists',
|
||||
|
@ -52,11 +52,11 @@ const fr = {
|
||||
offline: 'app hors ligne'
|
||||
},
|
||||
updates: {
|
||||
currentVersion: 'Version Actuelle',
|
||||
currentVersion: 'Version Actuelle Du Logiciel',
|
||||
currentWebuiVersion: 'Version Actuelle De La WebUI',
|
||||
versionNotAvailable: 'N/A',
|
||||
updateAvailable: "Vous n'utilisez pas la dernière version disponible : {version}",
|
||||
deemixVersion: 'Version de la bibliothèque deemix'
|
||||
deemixVersion: 'Version Actuelle De La Bibliothèque deemix'
|
||||
},
|
||||
titles: {
|
||||
usefulLinks: 'Liens Utiles',
|
||||
@ -83,6 +83,7 @@ const fr = {
|
||||
officialWebuiRepo: 'Répertoire De Dépôt Officiel De La WebUI',
|
||||
officialSubreddit: 'Subreddit Officiel',
|
||||
newsChannel: "Canal d'Informations",
|
||||
devlogChannel: 'Canal De Développement',
|
||||
questions: {
|
||||
text: `Si vous avez des questions ou des problèmes avec l'application, cherchez d'abord une solution dans le {subreddit}. Ensuite, si la solution ne s'y trouve pas, vous pouvez publier un message dans le subreddit en décrivant votre problème.`,
|
||||
subreddit: 'subreddit'
|
||||
@ -143,12 +144,14 @@ const fr = {
|
||||
noSpaceLeft: "L'espace disponible sur cet appareil est insuffisant !",
|
||||
albumDoesntExists: "Aucun album n'existe pour cette piste, impossible de collecter les informations nécessaires.",
|
||||
wrongLicense: 'Votre compte ne prend pas en charge la piste au débit souhaité.',
|
||||
wrongGeolocation: 'Votre compte ne prend pas en charge la piste depuis votre pays actuel.'
|
||||
wrongGeolocation: 'Votre compte ne prend pas en charge la piste depuis votre pays actuel.',
|
||||
wrongGeolocationNoAlternative:
|
||||
"Votre compte ne prend pas en charge la piste depuis votre pays actuel et aucune alternative n'a été trouvée."
|
||||
}
|
||||
},
|
||||
favorites: {
|
||||
title: 'Favoris',
|
||||
noPlaylists: "Aucune Playlist n'a été trouvée",
|
||||
noPlaylists: "Aucune Playlist Favorite n'a été trouvée",
|
||||
noAlbums: "Aucun Album Favori n'a été trouvé",
|
||||
noArtists: "Aucun Artiste Favori n'a été trouvé",
|
||||
noTracks: "Aucune Piste Favorite n'a été trouvée"
|
||||
@ -232,6 +235,7 @@ const fr = {
|
||||
title: 'Connexion',
|
||||
loggedIn: 'Vous êtes connecté en tant que {username}',
|
||||
arl: {
|
||||
title: 'Utiliser de préférence la connexion via ARL',
|
||||
question: 'Comment obtenir mon ARL personnel ?',
|
||||
update: "Actualiser l'ARL"
|
||||
},
|
||||
@ -300,7 +304,9 @@ const fr = {
|
||||
e: "Non, et ne pas tenir compte de l'extension du fichier"
|
||||
},
|
||||
fallbackBitrate: "Recourir à un débit plus faible si le débit préféré n'est pas disponible",
|
||||
fallbackSearch: "Rechercher la piste si le lien original n'est pas disponible",
|
||||
fallbackSearch: "Rechercher la piste ailleurs si le lien original n'est pas disponible",
|
||||
fallbackISRC: "Rechercher la piste à l'aide de son ISRC si le lien original n'est pas disponible",
|
||||
feelingLucky: "Utiliser les CDNs et les caches (ancienne méthode de téléchargement des pistes)",
|
||||
logErrors: "Créer un fichier journal d'erreurs",
|
||||
logSearched: 'Créer un fichier journal des pistes recherchées',
|
||||
createM3U8File: 'Créer un fichier de playlist',
|
||||
@ -334,6 +340,7 @@ const fr = {
|
||||
head: 'Métadonnées à sauvegarder',
|
||||
title: 'Titre',
|
||||
artist: 'Artiste',
|
||||
artists: 'Métadonnée supplémentaire ARTISTS',
|
||||
album: 'Album',
|
||||
cover: 'Pochette',
|
||||
trackNumber: 'Numéro De Piste',
|
||||
@ -356,7 +363,9 @@ const fr = {
|
||||
copyright: "Droits d'Auteur (Copyright)",
|
||||
composer: 'Compositeur',
|
||||
involvedPeople: 'Personnes Impliquées',
|
||||
source: 'ID de la source et de la piste'
|
||||
source: 'ID de la source et de la piste',
|
||||
artistsWarning:
|
||||
"La désactivation de la métadonnée ARTISTS sans utiliser la spécification standard ne préservera pas le support multi-artiste."
|
||||
},
|
||||
other: {
|
||||
title: 'Autre',
|
||||
@ -368,7 +377,9 @@ const fr = {
|
||||
nothing: "Enregistrer uniquement l'artiste principal",
|
||||
default: 'En utilisant la spécification standard',
|
||||
andFeat: 'En utilisant & et feat.',
|
||||
using: 'En utilisant "{separator}"'
|
||||
using: 'En utilisant "{separator}"',
|
||||
warning:
|
||||
"L'utilisation d'un séparateur autre que la spécification standard nécessitera l'ajout d'une métadonnée ARTISTS afin de préserver le support multi-artiste."
|
||||
},
|
||||
singleAlbumArtist: "Enregistrer uniquement l'artiste principal de l'album",
|
||||
albumVariousArtists: `Conserver "Various Artists" dans les Artistes de l'Album`,
|
||||
|
@ -82,6 +82,7 @@ const it = {
|
||||
officialWebuiRepo: `Repository Ufficiale dell'Interfaccia Web`,
|
||||
officialSubreddit: 'Subreddit Ufficiale',
|
||||
newsChannel: 'Canale delle news',
|
||||
devlogChannel: 'Canale Devlog',
|
||||
questions: {
|
||||
text: `Se dovessi avere domande o problemi con l'app, cerca prima una soluzione nel {subreddit}. Se non trovi nulla, puoi postare li il tuo problema.`,
|
||||
subreddit: 'subreddit ufficiale'
|
||||
|
@ -1,11 +1,11 @@
|
||||
const ko = {
|
||||
globals: {
|
||||
welcome: '잘왔다, deemix에',
|
||||
welcome: 'Deemix에 오신 것을 환영합니다',
|
||||
back: '뒤로',
|
||||
loading: '불러오는 중',
|
||||
download: '{thing} 다운로드',
|
||||
by: 'by {artist}',
|
||||
in: 'in {album}',
|
||||
by: '- {artist}',
|
||||
in: '{album} 중',
|
||||
download_hint: '다운로드',
|
||||
play_hint: '재생',
|
||||
toggle_download_tab_hint: '펼치기/접기',
|
||||
@ -52,7 +52,7 @@ const ko = {
|
||||
currentVersion: '현재 버전',
|
||||
currentWebuiVersion: '현재 WebUI 버전',
|
||||
versionNotAvailable: 'N/A',
|
||||
updateAvailable: `최신버전으로 업데이트 할 수 있습니다: {version}`,
|
||||
updateAvailable: `최신 버전 ({version})으로 업데이트 할 수 있습니다`,
|
||||
deemixVersion: 'deemix lib 버전'
|
||||
},
|
||||
titles: {
|
||||
@ -169,7 +169,7 @@ const ko = {
|
||||
}
|
||||
},
|
||||
search: {
|
||||
startSearching: '검색을 해보세요!',
|
||||
startSearching: '검색하세요!',
|
||||
description: '트랙, 아티스트, 재생목록, Deezer 링크 등으로 검색할 수 있습니다!',
|
||||
|
||||
fans: '{n}명의 팬들',
|
||||
@ -180,7 +180,7 @@ const ko = {
|
||||
noResultsPlaylist: '발견된 재생목록 없음'
|
||||
},
|
||||
searchbar: '원하는 것을 검색하세요 (링크를 붙여넣을 수도 있습니다)',
|
||||
downloads: '다운로드들',
|
||||
downloads: '다운로드',
|
||||
toasts: {
|
||||
restoringQueue: '다운로드 대기 열 복원중...',
|
||||
queueRestored: '다운로드 대기 열이 복원되었습니다!',
|
||||
@ -204,7 +204,7 @@ const ko = {
|
||||
loginNeededToDownload: '트랙을 다운로드하려면 로그인이 필요합니다!',
|
||||
deezerNotAvailable: 'Deezer 사이트는 현재 귀하의 국가에서 사용이 불가능합니다. VPN을 사용하세요.',
|
||||
startGeneratingItems: '{n}개의 항목 진행중...',
|
||||
finishGeneratingItems: '{n}개의 항목 생성.'
|
||||
finishGeneratingItems: '{n}개의 항목이 생성되었습니다.'
|
||||
},
|
||||
settings: {
|
||||
title: '설정',
|
||||
@ -264,12 +264,12 @@ const ko = {
|
||||
1: 'MP3 128kbps'
|
||||
},
|
||||
overwriteFile: {
|
||||
title: '파일을 덮어쓸까요?',
|
||||
y: '네, 파일을 덮어쓰세요',
|
||||
n: '아뇨, 파일을 덮어쓰지 마세요',
|
||||
t: '태그만 덮어쓰세요',
|
||||
b: '아뇨, 양쪽 다 놔두고 중복되는 파일에 번호를 추가하세요',
|
||||
e: '아뇨, 확장명을 변경하세요'
|
||||
title: '파일 덮어쓰기 여부',
|
||||
y: '파일 덮어쓰기',
|
||||
n: '파일 덮어쓰지 않기',
|
||||
t: '태그만 덮어쓰기',
|
||||
b: '모두 유지한 뒤 새 파일에 번호 넣기',
|
||||
e: '확장자 변경하기'
|
||||
},
|
||||
fallbackBitrate: '비트레이트 대비책',
|
||||
fallbackSearch: '검색 대비책',
|
||||
@ -289,10 +289,10 @@ const ko = {
|
||||
localArtworkSize: '외부 저장 그림 크기',
|
||||
embeddedArtworkSize: '내부 저장 그림 크기',
|
||||
localArtworkFormat: {
|
||||
title: '별도로 저장할 그림의 형식을 무엇으로 하시겠습니까?',
|
||||
title: '별도로 저장할 그림의 형식',
|
||||
jpg: 'jpeg 이미지',
|
||||
png: 'png 이미지',
|
||||
both: 'jpeg와 png 둘 다'
|
||||
both: 'jpeg와 png 모두'
|
||||
},
|
||||
jpegImageQuality: 'JPEG 이미지 품질',
|
||||
embeddedArtworkPNG: '포함된 그림의 형식을 PNG로 저장합니다',
|
||||
@ -376,7 +376,7 @@ const ko = {
|
||||
title: '스포티파이 기능',
|
||||
clientID: 'Spotify ClientID',
|
||||
clientSecret: 'Spotify Client Secret',
|
||||
username: 'Spotify 사용자이름',
|
||||
username: 'Spotify 사용자 이름',
|
||||
question: '스포티파이 기능들을 사용하려면 어떻게 해야 합니까?'
|
||||
},
|
||||
reset: '기본 설정으로 초기화',
|
||||
|
@ -9,12 +9,13 @@ const favoriteAlbums = ref([])
|
||||
const favoriteSpotifyPlaylists = ref([])
|
||||
const favoritePlaylists = ref([])
|
||||
const favoriteTracks = ref([])
|
||||
const lovedTracksPlaylist = ref('')
|
||||
const isLoggedWithSpotify = computed(() => store.getters.isLoggedWithSpotify)
|
||||
|
||||
const isRefreshingFavorites = ref(false)
|
||||
|
||||
const setAllFavorites = data => {
|
||||
const { tracks, albums, artists, playlists } = data
|
||||
const { tracks, albums, artists, playlists, lovedTracks } = data
|
||||
|
||||
isRefreshingFavorites.value = false
|
||||
|
||||
@ -22,6 +23,7 @@ const setAllFavorites = data => {
|
||||
favoriteAlbums.value = albums
|
||||
favoritePlaylists.value = playlists
|
||||
favoriteTracks.value = tracks
|
||||
lovedTracksPlaylist.value = lovedTracks
|
||||
}
|
||||
|
||||
const setSpotifyPlaylists = response => {
|
||||
@ -59,6 +61,7 @@ export const useFavorites = () => ({
|
||||
favoriteSpotifyPlaylists,
|
||||
favoritePlaylists,
|
||||
favoriteTracks,
|
||||
lovedTracksPlaylist,
|
||||
isRefreshingFavorites,
|
||||
refreshFavorites
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user