1.1.7 - cli, sorting, maximize, bugs...

This commit is contained in:
exttex 2020-11-08 18:01:02 +01:00
parent 8648e6df41
commit 0a467966cb
46 changed files with 940 additions and 426 deletions

View file

@ -10,9 +10,10 @@
height='28'>
<v-spacer></v-spacer>
<span>Freezer <span v-if='version'>v{{version}}</span></span>
<span style='position: absolute; left: 45%'>Freezer <span v-if='version'>v{{version}}</span></span>
<v-spacer></v-spacer>
<v-icon class='topbarbutton mx-2' @click='minimize'>mdi-window-minimize</v-icon>
<v-icon class='topbarbutton mx-2' @click='maximize'>mdi-window-maximize</v-icon>
<v-icon @click='exitApp' class='topbarbutton mx-2'>mdi-close</v-icon>
</v-system-bar>
@ -408,6 +409,10 @@ export default {
minimize() {
const {ipcRenderer} = window.require('electron');
ipcRenderer.send('minimize');
},
maximize() {
const {ipcRenderer} = window.require('electron');
ipcRenderer.send('maximize');
}
},
computed: {

View file

@ -54,6 +54,15 @@
<v-list-item-title>{{$t("Remove from library")}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
<!-- Share -->
<v-list-item dense @click='share'>
<v-list-item-icon>
<v-icon>mdi-share-variant</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{$t("Share")}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
<!-- Download -->
<v-list-item dense @click='download'>
<v-list-item-icon>
@ -167,6 +176,16 @@ export default {
}
this.album.tracks = tracks;
this.downloadDialog = true;
},
//Copy link
share() {
let copyElem = document.createElement('input');
copyElem.value = `https://deezer.com/album/${this.album.id}`;
document.body.appendChild(copyElem);
copyElem.select();
document.execCommand('copy');
document.body.removeChild(copyElem);
this.$root.globalSnackbar = this.$t('Link copied!');
}
}
};

View file

@ -26,7 +26,7 @@
<v-list-item-title>{{$t("Add to library")}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
<!-- Remvoe from library -->
<!-- Remove from library -->
<v-list-item dense @click='library' v-if='artist.library'>
<v-list-item-icon>
<v-icon>mdi-heart-remove</v-icon>
@ -35,6 +35,15 @@
<v-list-item-title>{{$t("Remove from library")}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
<!-- Share -->
<v-list-item dense @click='share'>
<v-list-item-icon>
<v-icon>mdi-share-variant</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{$t("Share")}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
@ -97,6 +106,16 @@ export default {
query: {artist: JSON.stringify(this.artist)}
});
this.$emit('clicked');
},
//Copy link
share() {
let copyElem = document.createElement('input');
copyElem.value = `https://deezer.com/artist/${this.artist.id}`;
document.body.appendChild(copyElem);
copyElem.select();
document.execCommand('copy');
document.body.removeChild(copyElem);
this.$root.globalSnackbar = this.$t('Link copied!');
}
}
}

View file

@ -54,12 +54,12 @@ export default {
return {
shown: true,
qualities: [
'Settings quality',
this.$t('Settings quality'),
'MP3 128kbps',
'MP3 320kbps',
'FLAC ~1441kbps'
],
qualityString: 'Settings quality',
qualityString: this.$t('Settings quality'),
autostart: true,
dShow: this.show
}

View file

@ -5,6 +5,23 @@
<v-progress-circular indeterminate></v-progress-circular>
</v-overlay>
<!-- Sort -->
<div class='px-4 d-flex' style='max-height: 50px;' v-if='!loading'>
<div class='text-overline pt-1 mx-2'>
{{albums.length}} {{$t("Albums")}}
</div>
<div style="max-width: 200px;" class='mx-2'>
<v-select class='px-2' dense solo :items='sortTypes' @change='sort' :label='$t("Sort by")'>
</v-select>
</div>
<div class='px-2' @click='reverseSort'>
<v-btn icon>
<v-icon v-if='isReversed'>mdi-sort-reverse-variant</v-icon>
<v-icon v-if='!isReversed'>mdi-sort-variant</v-icon>
</v-btn>
</div>
</div>
<v-lazy max-height="100" v-for='(album, index) in albums' :key='album.id'>
<AlbumTile :album='album' @remove='removed(index)'></AlbumTile>
</v-lazy>
@ -20,7 +37,16 @@ export default {
data() {
return {
albums: [],
loading: false
loading: false,
//Sort
isReversed: false,
sortTypes: [
this.$t('Date Added'),
this.$t('Name (A-Z)'),
this.$t('Artist (A-Z)')
],
unsorted: null
}
},
methods: {
@ -35,7 +61,35 @@ export default {
},
removed(index) {
this.albums.splice(index, 1);
}
},
//Sort changed
async sort(type) {
let index = this.sortTypes.indexOf(type);
//Copy original
if (!this.unsorted)
this.unsorted = JSON.parse(JSON.stringify(this.albums));
//Using indexes, so it can be translated later
this.isReversed = false;
switch (index) {
//Default
case 0:
this.albums = JSON.parse(JSON.stringify(this.unsorted));
break;
//Name
case 1:
this.albums = this.albums.sort((a, b) => {return a.title.localeCompare(b.title);});
break;
//Artist
case 2:
this.albums = this.albums.sort((a, b) => {return a.artistString.localeCompare(b.artistString);});
break;
}
},
async reverseSort() {
this.isReversed = !this.isReversed;
this.albums.reverse();
},
},
components: {
AlbumTile

View file

@ -5,6 +5,23 @@
<v-progress-circular indeterminate></v-progress-circular>
</v-overlay>
<!-- Sort -->
<div class='px-4 d-flex' style='max-height: 50px;' v-if='!loading'>
<div class='text-overline pt-1 mx-2'>
{{artists.length}} {{$t("Artists")}}
</div>
<div style="max-width: 200px;" class='mx-2'>
<v-select class='px-2' dense solo :items='sortTypes' @change='sort' :label='$t("Sort by")'>
</v-select>
</div>
<div class='px-2' @click='reverseSort'>
<v-btn icon>
<v-icon v-if='isReversed'>mdi-sort-reverse-variant</v-icon>
<v-icon v-if='!isReversed'>mdi-sort-variant</v-icon>
</v-btn>
</div>
</div>
<v-lazy max-height="100" v-for='(artist, index) in artists' :key='artist.id'>
<ArtistTile :artist='artist' @remove='removed(index)'></ArtistTile>
</v-lazy>
@ -23,7 +40,15 @@ export default {
data() {
return {
artists: [],
loading: false
loading: false,
//Sort
isReversed: false,
sortTypes: [
this.$t('Date Added'),
this.$t('Name (A-Z)')
],
unsorted: null
}
},
methods: {
@ -38,6 +63,30 @@ export default {
},
removed(index) {
this.artists.splice(index, 1);
},
//Sort changed
async sort(type) {
let index = this.sortTypes.indexOf(type);
//Copy original
if (!this.unsorted)
this.unsorted = JSON.parse(JSON.stringify(this.artists));
//Using indexes, so it can be translated later
this.isReversed = false;
switch (index) {
//Default
case 0:
this.artists = JSON.parse(JSON.stringify(this.unsorted));
break;
//Name
case 1:
this.artists = this.artists.sort((a, b) => {return a.name.localeCompare(b.name);});
break;
}
},
async reverseSort() {
this.isReversed = !this.isReversed;
this.artists.reverse();
}
},
mounted() {

View file

@ -5,17 +5,36 @@
<v-progress-circular indeterminate></v-progress-circular>
</v-overlay>
<!-- Create playlist -->
<v-btn class='ma-2 ml-3' color='primary' @click='popup = true'>
<v-icon left>mdi-playlist-plus</v-icon>
{{$t("Create new playlist")}}
</v-btn>
<div class='d-flex'>
<!-- Create playlist -->
<v-btn class='ma-2 ml-3' color='primary' @click='popup = true'>
<v-icon left>mdi-playlist-plus</v-icon>
{{$t("Create new playlist")}}
</v-btn>
<!-- Sort -->
<div class='mt-1 px-2 d-flex'>
<div class='text-overline pt-1 mx-2'>
{{playlists.length}} {{$t("Playlists")}}
</div>
<div style="max-width: 200px;" class='mx-2'>
<v-select class='px-2' dense solo :items='sortTypes' @change='sort' :label='$t("Sort by")'>
</v-select>
</div>
<div class='px-2' @click='reverseSort'>
<v-btn icon>
<v-icon v-if='isReversed'>mdi-sort-reverse-variant</v-icon>
<v-icon v-if='!isReversed'>mdi-sort-variant</v-icon>
</v-btn>
</div>
</div>
</div>
<v-dialog max-width="400px" v-model='popup'>
<PlaylistPopup @created='playlistCreated'></PlaylistPopup>
</v-dialog>
<v-lazy max-height="100" v-for='(playlist, index) in playlists' :key='playlist.id'>
<PlaylistTile :playlist='playlist' @remove='removed(index)'></PlaylistTile>
</v-lazy>
@ -36,7 +55,15 @@ export default {
return {
playlists: [],
loading: false,
popup: false
popup: false,
//Sort
isReversed: false,
sortTypes: [
this.$t('Date Added'),
this.$t('Name (A-Z)'),
],
unsorted: null
}
},
methods: {
@ -59,7 +86,31 @@ export default {
//On playlist remove
removed(i) {
this.playlists.splice(i, 1);
}
},
//Sort changed
async sort(type) {
let index = this.sortTypes.indexOf(type);
//Copy original
if (!this.unsorted)
this.unsorted = JSON.parse(JSON.stringify(this.playlists));
//Using indexes, so it can be translated later
this.isReversed = false;
switch (index) {
//Default
case 0:
this.playlists = JSON.parse(JSON.stringify(this.unsorted));
break;
//Name
case 1:
this.playlists = this.playlists.sort((a, b) => {return a.title.localeCompare(b.title);});
break;
}
},
async reverseSort() {
this.isReversed = !this.isReversed;
this.playlists.reverse();
},
},
mounted() {
//Initial load

View file

@ -55,6 +55,16 @@
<v-list-item-title>{{$t('Remove from library')}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
<!-- Share -->
<v-list-item dense @click='share'>
<v-list-item-icon>
<v-icon>mdi-share-variant</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{$t("Share")}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
<!-- Download -->
<v-list-item dense @click='download'>
@ -172,6 +182,16 @@ export default {
await this.$axios.put(`/library/playlist?id=${this.playlist.id}`);
this.$root.globalSnackbar = this.$t('Added to library!');
this.playlist.library = true;
},
//Copy link
share() {
let copyElem = document.createElement('input');
copyElem.value = `https://deezer.com/playlist/${this.playlist.id}`;
document.body.appendChild(copyElem);
copyElem.select();
document.execCommand('copy');
document.body.removeChild(copyElem);
this.$root.globalSnackbar = this.$t('Link copied!');
}
},
computed: {

View file

@ -1,5 +1,5 @@
<template>
<v-list-item two-line @click='$emit("click")'>
<v-list-item two-line @click='$emit("click")' :ripple='ripple'>
<v-list-item-avatar>
<v-img :src='track.albumArt.thumb'></v-img>
</v-list-item-avatar>
@ -93,6 +93,15 @@
<v-list-item-title>{{$t("Remove from playlist")}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
<!-- Share -->
<v-list-item dense @click='share'>
<v-list-item-icon>
<v-icon>mdi-share-variant</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{$t("Share")}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
<!-- Play track mix -->
<v-list-item dense @click='trackMix'>
<v-list-item-icon>
@ -174,6 +183,10 @@ export default {
type: String,
default: null
},
ripple: {
type: Boolean,
default: true
}
},
methods: {
//Add track next to queue
@ -231,6 +244,16 @@ export default {
};
this.$root.replaceQueue(res.data);
this.$root.playIndex(0);
},
//Copy link
share() {
let copyElem = document.createElement('input');
copyElem.value = `https://deezer.com/track/${this.track.id}`;
document.body.appendChild(copyElem);
copyElem.select();
document.execCommand('copy');
document.body.removeChild(copyElem);
this.$root.globalSnackbar = this.$t('Link copied!');
}
}
}

View file

@ -127,6 +127,12 @@
"Removed from library!": "الإزالة من المكتبة!",
"Removed from playlist!": "تمت الإزالة من قائمة التشغيل!",
"Playlist deleted!": "تم حذف قائمة التشغيل!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Delete": "حذف",
"Are you sure you want to delete this playlist?": "هل أنت متأكد من أنك تريد حذف قائمة التشغيل هذه؟",
"Force white tray icon": "فرض أيقونة شريط المهام البيضاء",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "فرض ايقونة شريط المهام (البيضاء) الافتراضية إذا تم الكشف عن الثيم بشكل غير صحيح. يتطلب إعادة التشغيل.",
"Share": "مشاركة",
"Settings quality": "جودة الإعدادات",
"Content language": "لغة المحتوى",
"Content country": "بلد المحتوى"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Aus der Wiedergabeliste entfernt!",
"Playlist deleted!": "Wiedergabeliste gelöscht!",
"Delete": "Löschen",
"Are you sure you want to delete this playlist?": "Bist du sicher, dass du diese Wiedergabeliste löschen willst?"
"Are you sure you want to delete this playlist?": "Bist du sicher, dass du diese Wiedergabeliste löschen willst?",
"Force white tray icon": "Erzwinge weißes Tray-Icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Standardsymbol (weiß) in der Kontrollleiste erzwingen, wenn Design falsch erkannt wurde. Neustart erforderlich.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -127,6 +127,12 @@
"Removed from library!": "Καταργήθηκε από τη βιβλιοθήκη!",
"Removed from playlist!": "Καταργήθηκε από τη λίστα αναπαραγωγής!",
"Playlist deleted!": "Η λίστα αναπαραγωγής διαγράφηκε!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Delete": "Διαγραφή",
"Are you sure you want to delete this playlist?": "Είστε βέβαιοι ότι θέλετε να διαγράψετε την λίστα αναπαραγωγής;",
"Force white tray icon": "Εξαναγκασμός λευκού εικονιδίου",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Επαναφορά προεπιλογής (λευκού) εικονιδίου σε περίπτωση σφάλματος θέματος. Απαιτείται επανεκκίνηση.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -130,5 +130,9 @@
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart."
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "¡Eliminado de la lista de reproducción!",
"Playlist deleted!": "¡Lista de reproducción eliminada!",
"Delete": "Eliminar",
"Are you sure you want to delete this playlist?": "¿Está seguro de querer eliminar la lista de reproducción?"
"Are you sure you want to delete this playlist?": "¿Está seguro de querer eliminar la lista de reproducción?",
"Force white tray icon": "Forzar icono blanco en la bandeja",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Forzar icono predeterminado en bandeja (blanco) si el tema no es detectado correctamente. Requiere reinicio.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -55,7 +55,7 @@
"Queue": "File d'attente",
"Total": "Total",
"Stop": "Arrêter",
"Start": "Début",
"Start": "Lancer",
"Show folder": "Afficher le dossier",
"Clear queue": "Effacer la liste d'attente",
"Playing from": "Lecture depuis",
@ -128,5 +128,11 @@
"Removed from playlist!": "Supprimé de la playlist !",
"Playlist deleted!": "Playlist supprimée !",
"Delete": "Supprimer",
"Are you sure you want to delete this playlist?": "Voulez-vous vraiment supprimer cette liste de lecture ?"
"Are you sure you want to delete this playlist?": "Voulez-vous vraiment supprimer cette liste de lecture ?",
"Force white tray icon": "Forcer l'icône blanche dans la zone de notification",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Forcer l'icône blanche par défaut dans la zone de notification si le thème n'est pas correctement détecté. Nécessite un redémarrage.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Dihapus dari daftar putar!",
"Playlist deleted!": "Daftar putar dihapus!",
"Delete": "Hapus",
"Are you sure you want to delete this playlist?": "Apakah kamu yakin ingin menghapus daftar putar ini?"
"Are you sure you want to delete this playlist?": "Apakah kamu yakin ingin menghapus daftar putar ini?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -110,23 +110,29 @@
"Settings saved!": "Impostazioni salvate!",
"Available only in Electron version!": "Disponibile solo nella versione Electron!",
"Crossfade (ms)": "Dissolvenza (ms)",
"Select primary color": "Select primary color",
"Light theme": "Light theme",
"Create folders for playlists": "Create folders for playlists",
"Select primary color": "Seleziona colore principale",
"Light theme": "Tema chiaro",
"Create folders for playlists": "Crea cartelle per le playlist",
"About": "About",
"Links:": "Links:",
"Links:": "Link:",
"Telegram Releases": "Telegram Releases",
"Telegram Group": "Telegram Group",
"Telegram Group": "Gruppo Telegram",
"Discord": "Discord",
"Telegram Android Group": "Telegram Android Group",
"Credits:": "Credits:",
"Agree": "Agree",
"Dismiss": "Dismiss",
"Added to playlist!": "Added to playlist!",
"Added to library!": "Added to library!",
"Removed from library!": "Removed from library!",
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Telegram Android Group": "Gruppo Telegram Android",
"Credits:": "Crediti:",
"Agree": "Accetta",
"Dismiss": "Rifiuta",
"Added to playlist!": "Aggiunto alla playlist!",
"Added to library!": "Aggiunto alla libreria!",
"Removed from library!": "Rimosso dalla libreria!",
"Removed from playlist!": "Rimosso dalla playlist!",
"Playlist deleted!": "Playlist eliminata!",
"Delete": "Elimina",
"Are you sure you want to delete this playlist?": "Sei sicuro di voler eliminare questa playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Usunięto z playlisty!",
"Playlist deleted!": "Playlista została usunięta!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -6,34 +6,34 @@
"Playlists": "Playlists",
"Albums": "Álbuns",
"Artists": "Artistas",
"More": "More",
"More": "Mais",
"Settings": "Configurações",
"Downloads": "Downloads",
"Search or paste Deezer URL. Use / to quickly focus.": "Procure ou cole a URL do intérprete. Use \"/\" para focar rapidamente.",
"Play": "Play",
"Search or paste Deezer URL. Use / to quickly focus.": "Procure ou cole a URL do Deezer. Use \"/\" para focar rapidamente.",
"Play": "Reproduzir",
"Add to library": "Adicionar à biblioteca",
"Download": "Download",
"fans": "fans",
"tracks": "faixas",
"Quality": "Qualidade",
"Estimated size:": "Tempo estimado:",
"Start downloading": "Iniciar download",
"Start downloading": "Começar a baixar",
"Cancel": "Cancelar",
"Stream logging is disabled!": "O registro de depuração extra está desativado!",
"Enable it in settings for history to work properly.": "Habilite nas configurações para que o histórico funcione corretamente.",
"History": "Histórico",
"Create new playlist": "Criar nova playlist",
"TRACKS": "FAIXAS",
"Sort by": "Sort by",
"Sort by": "Ordenar por",
"Date Added": "Data de adição",
"Name (A-Z)": "Nome (A-Z)",
"Artist (A-Z)": "Artista (A-Z)",
"Album (A-Z)": "Álbum (A-Z)",
"Error loading lyrics or lyrics not found!": "Erro ao carregar letras ou letras não encontradas!",
"Error loading lyrics or lyrics not found!": "Erro ao carregar letra ou letra não encontrada!",
"Create playlist": "Criar playlist",
"Create": "Criar",
"Add to playlist": "Adicionar à playlist",
"Create new": "Criar novo",
"Create new": "Criar nova",
"Remove": "Remover",
"Play next": "Reproduzir à seguir",
"Add to queue": "Adicionar à fila",
@ -49,7 +49,7 @@
"Play top": "Reproduzir no topo",
"Radio": "Rádio",
"Show all albums": "Mostrar todos os álbuns",
"Show all singles": "Mostrar todas as músicas",
"Show all singles": "Mostrar todos os singles",
"Show more": "Mostrar mais",
"Downloaded": "Baixados",
"Queue": "Fila de Reprodução",
@ -60,52 +60,52 @@
"Clear queue": "Limpar lista",
"Playing from": "Reproduzindo de",
"Info": "Informações",
"Lyrics": "Letras",
"Lyrics": "Letra",
"Track number": "Número de faixa",
"Disk number": "Numero de disco",
"Explicit": "Explicito",
"Explicit": "Explícito",
"Source": "Fonte",
"ID": "Identificação",
"Error logging in!": "Erro de login!",
"Please try again later, or try another account.": "Por favor, tente novamente mais tarde ou tente outra conta.",
"Logout": "Encerrar sessão",
"Logout": "Desconectar",
"Login using browser": "Login usando o navegador",
"Please login using your Deezer account:": "Faça login usando sua conta do Deezer:",
"...or paste your ARL/Token below:": "...ou cole seu ARL/Token abaixo:",
"ARL/Token": "ARL/Token",
"Login": "Login",
"By using this program, you disagree with Deezer's ToS.": "Ao usar este programa, você discorda do Acordo de Assinatura do Deezer.",
"By using this program, you disagree with Deezer's ToS.": "Ao usar este programa, você discorda dos termos e condições de uso do Deezer.",
"Only in Electron version!": "Apenas na versão do Electron!",
"Search results for:": "Buscar resultados para:",
"Error loading data!": "Error loading data!",
"Try again later!": "Try again later!",
"Search": "Search",
"Streaming Quality": "Streaming Quality",
"Download Quality": "Download Quality",
"Downloads Directory": "Downloads Directory",
"Simultaneous downloads": "Simultaneous downloads",
"Always show download confirm dialog before downloading.": "Always show download confirm dialog before downloading.",
"Show download dialog": "Show download dialog",
"Create folders for artists": "Create folders for artists",
"Create folders for albums": "Create folders for albums",
"Download lyrics": "Download lyrics",
"Variables": "Variables",
"UI": "UI",
"Show autocomplete in search": "Show autocomplete in search",
"Integrations": "Integrations",
"This allows listening history, flow and recommendations to work properly.": "This allows listening history, flow and recommendations to work properly.",
"Log track listens to Deezer": "Log track listens to Deezer",
"Connect your LastFM account to allow scrobbling.": "Connect your LastFM account to allow scrobbling.",
"Login with LastFM": "Login with LastFM",
"Disconnect LastFM": "Disconnect LastFM",
"Error loading data!": "Erro ao carregar dados!",
"Try again later!": "Tente novamente mais tarde!",
"Search": "Busca",
"Streaming Quality": "Qualidade do streaming",
"Download Quality": "Qualiadade do download",
"Downloads Directory": "Pasta de Download",
"Simultaneous downloads": "Downloads simultâneos",
"Always show download confirm dialog before downloading.": "Sempre mostrar diálogo de confirmação de download antes de baixar.",
"Show download dialog": "Mostrar diálogo de download",
"Create folders for artists": "Criar pastas para artistas",
"Create folders for albums": "Criar pastas para álbuns",
"Download lyrics": "Baixar letra",
"Variables": "Variáveis",
"UI": "IU",
"Show autocomplete in search": "Mostrar autocompletar na busca",
"Integrations": "Integrações",
"This allows listening history, flow and recommendations to work properly.": "Isto permite que o histórico de ouvidas, flow e recomendações funcionem corretamente.",
"Log track listens to Deezer": "Log de faixas ouvidas para o Deezer",
"Connect your LastFM account to allow scrobbling.": "Conecte sua conta do LastFM para permitir o scrobbling.",
"Login with LastFM": "Login com LastFM",
"Disconnect LastFM": "Desconectar LastFM",
"Requires restart to apply!": "Requer reinicialização do aplicativo para aplicar!",
"Enable Discord Rich Presence, requires restart to toggle!": "Ativar o Rich Presence do Discord, requer reiniciar para alternar!",
"Discord Rich Presence": "Habilitar o Discord",
"Discord Rich Presence": "Discord Rich Presence",
"Enable Discord join button for syncing tracks, requires restart to toggle!": "Ativar o botão de adesão do Discord para sincronizar faixas requer reinicialização para alternar!",
"Discord Join Button": "Botão de Entrada Discord",
"Other": "Outros",
"Other": "Outro",
"Minimize to tray": "Minimizar para a bandeja",
"Don't minimize to tray": "Minimizar automaticamente para a bandeja",
"Don't minimize to tray": "Não minimizar para a bandeja",
"Close on exit": "Fechar ao sair",
"Settings saved!": "Configurações salvas!",
"Available only in Electron version!": "Disponível apenas na versão completa!",
@ -118,15 +118,21 @@
"Telegram Releases": "Versões no Telegram",
"Telegram Group": "Grupo do Telegram",
"Discord": "Discord",
"Telegram Android Group": "Grupo Android do Telegram",
"Telegram Android Group": "Grupo do Android no Telegram",
"Credits:": "Créditos:",
"Agree": "Concordo",
"Dismiss": "Dismiss",
"Added to playlist!": "Added to playlist!",
"Added to library!": "Added to library!",
"Removed from library!": "Removed from library!",
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Dismiss": "Dispensar",
"Added to playlist!": "Adicionar à playlist!",
"Added to library!": "Adicionado à biblioteca!",
"Removed from library!": "Removido da biblioteca!",
"Removed from playlist!": "Removido da playlist!",
"Playlist deleted!": "Playlist deletada!",
"Delete": "Deletar",
"Are you sure you want to delete this playlist?": "Você tem certeza que deseja excluir esta playlist?",
"Force white tray icon": "Forçar ícone de bandeja branco",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Forçar ícone de bandeja (branco) padrão se o tema for detectado incorretamente. Requer reinicialização.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -120,13 +120,19 @@
"Discord": "Discord",
"Telegram Android Group": "Обсуждение Freezer Android",
"Credits:": "Благодарность:",
"Agree": "Agree",
"Dismiss": "Dismiss",
"Added to playlist!": "Added to playlist!",
"Added to library!": "Added to library!",
"Removed from library!": "Removed from library!",
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Agree": "Согласен",
"Dismiss": "Отмена",
"Added to playlist!": "Добавлено в плейлист!",
"Added to library!": "Добавлено в избранное!",
"Removed from library!": "Удалено из Избранного!",
"Removed from playlist!": "Удалено из плейлиста!",
"Playlist deleted!": "Плейлист удален!",
"Delete": "Удалить",
"Are you sure you want to delete this playlist?": "Вы точно хотите удалить этот плейлист?",
"Force white tray icon": "Белый значок в трее",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Принудительно использовать белый значок, если тема определена неправильно. Требуется перезапуск.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Odstránené z playlistu!",
"Playlist deleted!": "Playlist odstránený!",
"Delete": "Odstrániť",
"Are you sure you want to delete this playlist?": "Naozaj chcete odstrániť tento playlist?"
"Are you sure you want to delete this playlist?": "Naozaj chcete odstrániť tento playlist?",
"Force white tray icon": "Vynútiť bielu ikonu v lište",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Vynútiť predvolenú (bielu) ikonu v lište, ak je motív nesprávne zistený. Vyžaduje sa reštart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Видалено з плейлиста!",
"Playlist deleted!": "Плейлист видалено!",
"Delete": "Видалити",
"Are you sure you want to delete this playlist?": "Ви впевнені, що хочете видалити цей плейлист?"
"Are you sure you want to delete this playlist?": "Ви впевнені, що хочете видалити цей плейлист?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -128,5 +128,11 @@
"Removed from playlist!": "Removed from playlist!",
"Playlist deleted!": "Playlist deleted!",
"Delete": "Delete",
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?"
"Are you sure you want to delete this playlist?": "Are you sure you want to delete this playlist?",
"Force white tray icon": "Force white tray icon",
"Force default (white) tray icon if theme incorrectly detected. Requires restart.": "Force default (white) tray icon if theme incorrectly detected. Requires restart.",
"Share": "Share",
"Settings quality": "Settings quality",
"Content language": "Content language",
"Content country": "Content country"
}

View file

@ -234,7 +234,7 @@ new Vue({
}
//Crossfade
if (this.settings.crossfadeDuration > 0 && this.position >= (this.duration() - this.settings.crossfadeDuration) && this.state == 2 && this.gapless.audio && !this.gapless.crossfade) {
if (this.settings.crossfadeDuration > 0 && this.position >= (this.duration() - this.settings.crossfadeDuration) && this.state == 2 && this.gapless.audio && !this.gapless.crossfade && this.gapless.track) {
this.gapless.crossfade = true;
let currentVolume = this.audio.volume;
let oldAudio = this.audio;
@ -249,11 +249,15 @@ new Vue({
this.configureAudio();
this.updateMediaSession();
this.audio.volume = 0.0;
let volumeStep = currentVolume / (this.settings.crossfadeDuration / 50);
for (let i=0; i<(this.settings.crossfadeDuration / 50); i++) {
if ((oldAudio.volume - volumeStep) > 0)
oldAudio.volume -= volumeStep;
this.audio.volume += volumeStep;
//Prevent going over
if (this.audio.volume >= currentVolume)
break;
await new Promise((res) => setTimeout(() => res(), 50));
}
oldAudio.pause();
@ -355,11 +359,11 @@ new Vue({
//Reset gapless playback meta
resetGapless() {
this.gapless = {promise: null,audio: null,info: null,track: null,index:null};
this.gapless = {crossfade: false,promise: null,audio: null,info: null,track: null,index:null};
},
//Load next track for gapless
async loadGapless() {
if (this.loaders != 0 || this.gapless.promise || this.gapless.audio) return;
if (this.loaders != 0 || this.gapless.promise || this.gapless.audio || this.gapless.crossfade) return;
//Repeat list
if (this.repeat == 1 && this.queue.index == this.queue.data.length - 1) {
@ -385,7 +389,7 @@ new Vue({
}
this.gapless.info = info
this.gapless.audio = new Audio(`${window.location.origin}${info.url}`);
this.gapless.audio.volume = 0;
this.gapless.audio.volume = 0.00;
this.gapless.audio.preload = 'auto';
this.gapless.crossfade = false;

View file

@ -50,7 +50,7 @@
<v-list-item-subtitle>Developer</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<v-list-item @click='openUrl("https://git.fuwafuwa.moe/RemixDev/deemix")'>
<v-list-item>
<v-list-item-content>
<v-list-item-title class='font-weight-bold'>Deemix</v-list-item-title>
<v-list-item-subtitle>Much better app &lt;3</v-list-item-subtitle>

View file

@ -11,7 +11,7 @@
<!-- Split to half -->
<v-row class='pa-2' no-gutters justify="center">
<!-- Left side (track info...) -->
<v-col class='col-6 text-center' align-self="center">
<v-col class='col-12 col-sm-6 text-center' align-self="center">
<v-img
:src='$root.track.albumArt.full'
:lazy-src="$root.track.albumArt.thumb"
@ -94,6 +94,10 @@
<v-icon>mdi-download</v-icon>
</v-btn>
<v-btn icon @click='share'>
<v-icon>mdi-share-variant</v-icon>
</v-btn>
<!-- Volume -->
<v-slider
min='0.00'
@ -118,7 +122,7 @@
</v-col>
<!-- Right side -->
<v-col class='col-6 pt-4'>
<v-col class='col-12 col-sm-6 pt-4'>
<v-tabs v-model='tab'>
<v-tab key='queue'>
{{$t("Queue")}}
@ -135,18 +139,18 @@
<!-- Queue tab -->
<v-tab-item key='queue'>
<v-list two-line avatar class='overflow-y-auto' style='max-height: calc(100vh - 160px)'>
<v-lazy
min-height="1"
transition="fade-transition"
v-for="(track, index) in $root.queue.data"
:key='index + "q" + track.id'
><TrackTile
:track='track'
@click='$root.playIndex(index)'
@redirect='close'
></TrackTile>
</v-lazy>
<draggable v-model='$root.queue.data' @change='queueMove'>
<div v-for="(track, index) in $root.queue.data" :key='index + "q" + track.id'>
<v-lazy min-height="1" transition="fade-transition">
<TrackTile
:track='track'
@click='$root.playIndex(index)'
@redirect='close'
:ripple='false'
></TrackTile>
</v-lazy>
</div>
</draggable>
</v-list>
</v-tab-item>
<!-- Info tab -->
@ -238,10 +242,12 @@ import PlaylistPopup from '@/components/PlaylistPopup.vue';
import Lyrics from '@/components/Lyrics.vue';
import DownloadDialog from '@/components/DownloadDialog.vue';
import draggable from 'vuedraggable';
export default {
name: 'FullscreenPlayer',
components: {
TrackTile, ArtistTile, AlbumTile, PlaylistPopup, Lyrics, DownloadDialog
TrackTile, ArtistTile, AlbumTile, PlaylistPopup, Lyrics, DownloadDialog, draggable
},
data() {
return {
@ -312,6 +318,19 @@ export default {
}
//Update index
this.$root.queue.index = this.$root.queue.data.findIndex(t => t.id == this.$root.track.id);
},
//Copy link
share() {
let copyElem = document.createElement('input');
copyElem.value = `https://deezer.com/track/${this.$root.track.id}`;
document.body.appendChild(copyElem);
copyElem.select();
document.execCommand('copy');
document.body.removeChild(copyElem);
this.$root.globalSnackbar = this.$t('Link copied!');
},
queueMove() {
this.$root.queue.index = this.$root.queue.data.findIndex(t => t.id == this.$root.track.id);
}
},
mounted() {

View file

@ -22,7 +22,7 @@
<span class='text-subtitle-2'>{{$numberString(playlist.fans)}} {{$t('fans')}}</span><br>
</div>
<div class='my-2'>
<div class='my-2 d-flex'>
<v-btn color='primary' class='mr-1' @click='play'>
<v-icon left>mdi-play</v-icon>
{{$t('Play')}}
@ -45,6 +45,16 @@
<v-icon left>mdi-delete</v-icon>
{{$t('Delete')}}
</v-btn>
<div class='mx-2' dense stlye='max-width: 120px;'>
<v-select class='px-2' dense solo :items='sortTypes' @change='sort' :label='$t("Sort by")'>
</v-select>
</div>
<div class='px-2' @click='reverseSort'>
<v-btn icon>
<v-icon v-if='isReversed'>mdi-sort-reverse-variant</v-icon>
<v-icon v-if='!isReversed'>mdi-sort-variant</v-icon>
</v-btn>
</div>
</div>
</div>
</v-card>
@ -109,7 +119,16 @@ export default {
//Add to library button
libraryLoading: false,
downloadDialog: false,
deleteDialog: false
deleteDialog: false,
//Sort
sortTypes: [
this.$t('Date Added'),
this.$t('Name (A-Z)'),
this.$t('Artist (A-Z)'),
this.$t('Album (A-Z)')
],
isReversed: false
}
},
methods: {
@ -209,7 +228,45 @@ export default {
async deletePlaylist() {
await this.$axios.delete(`/playlist/${this.playlist.id}`);
this.$router.go(-1);
}
},
//Sort changed
async sort(type) {
let index = this.sortTypes.indexOf(type);
//Preload all tracks
if (this.playlist.tracks.length < this.playlist.trackCount)
await this.loadAllTracks();
//Copy original
if (!this.tracksUnsorted)
this.tracksUnsorted = JSON.parse(JSON.stringify(this.playlist.tracks));
//Using indexes, so it can be translated later
this.isReversed = false;
switch (index) {
//Default
case 0:
this.tracks = JSON.parse(JSON.stringify(this.tracksUnsorted));
break;
//Name
case 1:
this.tracks = this.playlist.tracks.sort((a, b) => {return a.title.localeCompare(b.title);});
break;
//Artist
case 2:
this.tracks = this.playlist.tracks.sort((a, b) => {return a.artistString.localeCompare(b.artistString);});
break;
//Album
case 3:
this.tracks = this.playlist.tracks.sort((a, b) => {return a.album.title.localeCompare(b.album.title);});
break;
}
},
async reverseSort() {
//Preload tracks if not sorted yet
if (this.playlist.tracks.length < this.playlist.trackCount)
await this.sort(0);
this.isReversed = !this.isReversed;
this.tracks.reverse();
},
},
mounted() {
this.initialLoad();

View file

@ -211,6 +211,23 @@
<v-subheader>{{$t("Other")}}</v-subheader>
<v-divider></v-divider>
<div class='d-flex mx-4 pt-2'>
<v-select
v-model='$root.settings.contentLanguage'
:items='languageList'
:label='$t("Content language")'
class='mr-4'
></v-select>
<v-select
v-model='$root.settings.contentCountry'
:items='countryList'
:label='$t("Content country")'
class='ml-4'
></v-select>
</div>
<!-- Minimize to tray -->
<v-list-item v-if='$root.settings.electron'>
<v-list-item-action>
@ -283,6 +300,7 @@
</template>
<script>
export default {
name: 'Settings',
data() {
@ -320,7 +338,11 @@ export default {
primaryColorIndex: 0,
primaries: ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4',
'#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800', '#FF5722',
'#795548', '#607D8B', '#9E9E9E']
'#795548', '#607D8B', '#9E9E9E'],
//Lists from Deezer website
languageList: ["me", "da", "de", "en", "us", "es", "mx", "fr", "hr", "id", "it", "hu", "ms", "nl", "no", "pl", "br", "pt", "ru", "ro", "sq", "sk", "sl", "sr", "fi", "sv", "tr", "cs", "bg", "uk", "he", "ar", "th", "cn", "ja", "ko"],
countryList: ["AF", "AL", "DZ", "AO", "AI", "AG", "AR", "AM", "AU", "AT", "AZ", "BH", "BD", "BB", "BY", "BE", "BJ", "BT", "BO", "BA", "BW", "BR", "IO", "VG", "BN", "BG", "BF", "BI", "KH", "CM", "CA", "CV", "KY", "CF", "TD", "CL", "CX", "CC", "CO", "CK", "CR", "HR", "CY", "CZ", "CD", "DK", "DJ", "DM", "TL", "EC", "EG", "SV", "GQ", "ER", "EE", "ET", "FM", "FJ", "FI", "FR", "GA", "GM", "GE", "DE", "GH", "GR", "GD", "GT", "GN", "GW", "HN", "HU", "IS", "ID", "IQ", "IE", "IL", "IT", "JM", "JP", "JO", "KZ", "KE", "KI", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LT", "LU", "MK", "MG", "MW", "MY", "ML", "MT", "MH", "MR", "MU", "MX", "MD", "MN", "ME", "MS", "MA", "MZ", "NA", "NR", "NP", "NZ", "NI", "NE", "NG", "NU", "NF", "NO", "OM", "PK", "PW", "PA", "PG", "PY", "PE", "PL", "PT", "QA", "CG", "RO", "RU", "RW", "KN", "LC", "VC", "WS", "ST", "SA", "SN", "RS", "SC", "SL", "SG", "SK", "SI", "SO", "ZA", "ES", "LK", "SJ", "SZ", "SE", "CH", "TJ", "TZ", "TH", "KM", "FK", "CI", "MV", "NL", "PH", "PN", "SB", "TG", "TK", "TO", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "US", "UY", "UZ", "VU", "VE", "VN", "YE", "ZM", "ZW"],
}
},
methods: {