From 9585adf528c69371011c3a5c657fdeea65ee4cad Mon Sep 17 00:00:00 2001 From: exttex Date: Sun, 11 Oct 2020 22:06:29 +0200 Subject: [PATCH] 0.5.2 - Download fixes, translation updates, system theme --- README.md | 2 + .../app/src/main/java/f/f/freezer/Deezer.java | 85 +++++- .../java/f/f/freezer/DownloadService.java | 130 ++++++--- .../main/java/f/f/freezer/MainActivity.java | 1 + audio_service | 2 +- lib/api/download.dart | 2 +- lib/api/player.dart | 32 +-- lib/languages/ar_ar.dart | 10 +- lib/languages/es_es.dart | 93 ++++--- lib/languages/it_it.dart | 64 ++--- lib/languages/ro_ro.dart | 230 ++++++++++++++++ lib/languages/ru_ru.dart | 252 +++++++++++------- lib/languages/tr_tr.dart | 231 ++++++++++++++++ lib/settings.dart | 128 ++++----- lib/settings.g.dart | 4 +- lib/translations.i18n.dart | 6 +- lib/ui/downloads_screen.dart | 2 +- lib/ui/login_screen.dart | 2 +- lib/ui/settings_screen.dart | 81 ++++-- pubspec.yaml | 2 +- 20 files changed, 1028 insertions(+), 331 deletions(-) create mode 100644 lib/languages/ro_ro.dart create mode 100644 lib/languages/tr_tr.dart diff --git a/README.md b/README.md index fd0f036..9d27de0 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ VIRGIN_KLM: Greek koreezzz: Korean Fwwwwwwwwwweze: French kobyrevah: Hebrew +MicroMihai: Romanian +HoScHaKaL: Turkish ### just_audio, audio_service This app depends on modified just_audio and audio_service plugins with Deezer support. diff --git a/android/app/src/main/java/f/f/freezer/Deezer.java b/android/app/src/main/java/f/f/freezer/Deezer.java index 12fb411..f27e777 100644 --- a/android/app/src/main/java/f/f/freezer/Deezer.java +++ b/android/app/src/main/java/f/f/freezer/Deezer.java @@ -38,10 +38,30 @@ import javax.net.ssl.HttpsURLConnection; public class Deezer { DownloadLog logger; + String token; + String arl; + String sid; + boolean authorized = false; + boolean authorizing = false; //Initialize for logging - void init(DownloadLog logger) { + void init(DownloadLog logger, String arl) { this.logger = logger; + this.arl = arl; + } + + //Authorize GWLight API + public void authorize() { + if (!authorized || sid == null || token == null) { + authorizing = true; + try { + callGWAPI("deezer.getUserData", "{}"); + authorized = true; + } catch (Exception e) { + logger.warn("Error authorizing to Deezer API! " + e.toString()); + } + } + authorizing = false; } //Get guest SID cookie from deezer.com @@ -59,11 +79,18 @@ public class Deezer { return sid; } - //Same as gw_light API, but doesn't need authentication - public static JSONObject callMobileAPI(String method, String params) throws Exception{ - String sid = Deezer.getSidCookie(); + public JSONObject callGWAPI(String method, String params) throws Exception { + if (sid == null) + this.sid = Deezer.getSidCookie(); - URL url = new URL("https://api.deezer.com/1.0/gateway.php?api_key=4VCYIJUCDLOUELGD1V8WBVYBNVDYOXEWSLLZDONGBBDFVXTZJRXPR29JRLQFO6ZE&sid=" + sid + "&input=3&output=3&method=" + method); + //Get token + if (token == null) { + token = "null"; + callGWAPI("deezer.getUserData", "{}"); + } + + //Call + URL url = new URL("https://www.deezer.com/ajax/gw-light.php?method=" + method + "&input=3&api_version=1.0&api_token=" + token); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setConnectTimeout(20000); connection.setDoOutput(true); @@ -73,6 +100,8 @@ public class Deezer { connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("Accept", "*/*"); connection.setRequestProperty("Content-Length", Integer.toString(params.getBytes(StandardCharsets.UTF_8).length)); + String cookies = "arl=" + arl + "; sid=" + sid; + connection.setRequestProperty("Cookie", cookies); //Write body DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); @@ -87,9 +116,26 @@ public class Deezer { //Parse JSON JSONObject out = new JSONObject(data); + + //Save token + if ((token == null || token.equals("null")) && method.equals("deezer.getUserData")) { + token = out.getJSONObject("results").getString("checkForm"); + //SID + try { + String newSid = null; + for (String cookie : connection.getHeaderFields().get("Set-Cookie")) { + if (cookie.startsWith("sid=")) { + newSid = cookie.split(";")[0].split("=")[1]; + } + } + this.sid = newSid; + } catch (Exception ignored) {} + } + return out; } + //api.deezer.com/$method/$param public static JSONObject callPublicAPI(String method, String param) throws Exception { URL url = new URL("https://api.deezer.com/" + method + "/" + param); @@ -267,7 +313,7 @@ public class Deezer { } //Tag track with data from API - public static void tagTrack(String path, JSONObject publicTrack, JSONObject publicAlbum, String cover) throws Exception { + public static void tagTrack(String path, JSONObject publicTrack, JSONObject publicAlbum, String cover, JSONObject lyricsData) throws Exception { TagOptionSingleton.getInstance().setAndroid(true); //Load file AudioFile f = AudioFileIO.read(new File(path)); @@ -281,21 +327,38 @@ public class Deezer { tag.setField(FieldKey.TITLE, publicTrack.getString("title")); tag.setField(FieldKey.ALBUM, publicTrack.getJSONObject("album").getString("title")); //Artist + String artists = ""; for (int i=0; i 2) + tag.addField(FieldKey.GENRE, genres.substring(2)); + File coverFile = new File(cover); boolean addCover = (coverFile.exists() && coverFile.length() > 0); diff --git a/android/app/src/main/java/f/f/freezer/DownloadService.java b/android/app/src/main/java/f/f/freezer/DownloadService.java index 36fd6d1..be5e860 100644 --- a/android/app/src/main/java/f/f/freezer/DownloadService.java +++ b/android/app/src/main/java/f/f/freezer/DownloadService.java @@ -25,11 +25,13 @@ import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.text.DecimalFormat; @@ -83,7 +85,7 @@ public class DownloadService extends Service { //Setup logger, deezer api logger.open(context); - deezer.init(logger); + deezer.init(logger, ""); //Get DB DownloadsDatabase dbHelper = new DownloadsDatabase(getApplicationContext()); @@ -215,7 +217,9 @@ public class DownloadService extends Service { updating = true; while (updateRequests.size() > 0) { updateQueue(); - updateRequests.remove(0); + //Because threading + if (updateRequests.size() > 0) + updateRequests.remove(0); } } updating = false; @@ -280,6 +284,49 @@ public class DownloadService extends Service { //Set state download.state = Download.DownloadState.DOWNLOADING; + //Authorize deezer api + if (!deezer.authorized && !deezer.authorizing) + deezer.authorize(); + + while (deezer.authorizing) + try {Thread.sleep(50);} catch (Exception ignored) {} + + //Fetch metadata + try { + trackJson = Deezer.callPublicAPI("track", download.trackId); + albumJson = Deezer.callPublicAPI("album", Integer.toString(trackJson.getJSONObject("album").getInt("id"))); + } catch (Exception e) { + logger.error("Unable to fetch track and album metadata! " + e.toString(), download); + e.printStackTrace(); + download.state = Download.DownloadState.ERROR; + exit(); + return; + } + + //ISRC Fallback + try { + if (trackJson.has("available_countries") && trackJson.getJSONArray("available_countries").length() == 0) { + logger.warn("ISRC Fallback!", download); + JSONObject newTrackJson = Deezer.callPublicAPI("track", "isrc:" + trackJson.getString("isrc")); + //Same track check + if (newTrackJson.getJSONArray("available_countries").length() == 0 || newTrackJson.getInt("id") == trackJson.getInt("id")) throw new Exception("No more to fallback!"); + //Get private data + JSONObject privateJson = deezer.callGWAPI("song.getListData", "{\"sng_ids\": [" + newTrackJson.getInt("id") + "]}"); + JSONObject trackData = privateJson.getJSONObject("results").getJSONArray("data").getJSONObject(0); + download.trackId = trackData.getString("SNG_ID"); + download.md5origin = trackData.getString("MD5_ORIGIN"); + download.mediaVersion = trackData.getString("MEDIA_VERSION"); + run(); + return; + } + } catch (Exception e) { + logger.error("ISRC Fallback failed, track unavailable! " + e.toString()); + download.state = Download.DownloadState.DEEZER_ERROR; + exit(); + return; + } + + //Quality fallback int newQuality; try { @@ -300,18 +347,6 @@ public class DownloadService extends Service { download.quality = newQuality; if (!download.priv) { - //Fetch metadata - try { - trackJson = Deezer.callPublicAPI("track", download.trackId); - albumJson = Deezer.callPublicAPI("album", Integer.toString(trackJson.getJSONObject("album").getInt("id"))); - } catch (Exception e) { - logger.error("Unable to fetch track and album metadata! " + e.toString(), download); - e.printStackTrace(); - download.state = Download.DownloadState.ERROR; - exit(); - return; - } - //Check file try { outFile = new File(Deezer.generateFilename(download.path, trackJson, albumJson, newQuality)); @@ -422,21 +457,29 @@ public class DownloadService extends Service { //Create dirs and copy parentDir.mkdirs(); if (!tmpFile.renameTo(outFile)) { - boolean error = true; try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Files.move(tmpFile.toPath(), outFile.toPath(), StandardCopyOption.REPLACE_EXISTING); tmpFile.delete(); - error = false; + } else { + //Android AudioService.queue.indexWhere((mi) => mi.id == AudioService.currentMediaItem?.id??'Random string so it returns -1'); Future start() async { - //Subscribe to custom events + //Subscribe to custom events _customEventSubscription = AudioService.customEventStream.listen((event) async { if (!(event is Map)) return; if (event['action'] == 'onLoad') { @@ -78,11 +78,10 @@ class PlayerHelper { } }); _mediaItemSubscription = AudioService.currentMediaItemStream.listen((event) { + if (event == null) return; //Save queue AudioService.customAction('saveQueue'); - //Add to history - if (event == null) return; if (cache.history == null) cache.history = []; if (cache.history.length > 0 && cache.history.last.id == event.id) return; cache.history.add(Track.fromMediaItem(event)); @@ -90,21 +89,24 @@ class PlayerHelper { }); //Start audio_service - startService(); + await startService(); } Future startService() async { - if (AudioService.running) return; - await AudioService.start( - backgroundTaskEntrypoint: backgroundTaskEntrypoint, - androidEnableQueue: true, - androidStopForegroundOnPause: false, - androidNotificationOngoing: false, - androidNotificationClickStartsActivity: false, - androidNotificationChannelDescription: 'Freezer', - androidNotificationChannelName: 'Freezer', - androidNotificationIcon: 'drawable/ic_logo', - ); + if (AudioService.running && AudioService.connected) return; + if (!AudioService.connected) + await AudioService.connect(); + if (!AudioService.running) + await AudioService.start( + backgroundTaskEntrypoint: backgroundTaskEntrypoint, + androidEnableQueue: true, + androidStopForegroundOnPause: false, + androidNotificationOngoing: false, + androidNotificationClickStartsActivity: true, + androidNotificationChannelDescription: 'Freezer', + androidNotificationChannelName: 'Freezer', + androidNotificationIcon: 'drawable/ic_logo', + ); } Future toggleShuffle() async { diff --git a/lib/languages/ar_ar.dart b/lib/languages/ar_ar.dart index 57b4e29..89fbc5a 100644 --- a/lib/languages/ar_ar.dart +++ b/lib/languages/ar_ar.dart @@ -167,8 +167,8 @@ const language_ar_ar = { "Language changed, please restart Freezer to apply!": "تم تغيير اللغة، الرجاء إعادة تشغيل فريزر لتطبيق!", "Importing...": "جار الاستيراد...", "Radio": "راديو", - - //0.5.0 Strings: + + //0.5.0 Strings: "Storage permission denied!": "رفض إذن التخزين!", "Failed": "فشل", "Queued": "في قائمة الانتظار", @@ -198,6 +198,10 @@ const language_ar_ar = { "Download Log": "سجل التنزيل", "Repository": "Repository", "Source code, report issues there.": "كود المصدر ، ابلغ عن المشاكل هنا.", - + + //0.5.2 Strings: + "Use system theme": "استخدم ثيم النظام", + "Light": "ابيض", + } }; diff --git a/lib/languages/es_es.dart b/lib/languages/es_es.dart index a25682c..a626fe0 100644 --- a/lib/languages/es_es.dart +++ b/lib/languages/es_es.dart @@ -9,7 +9,8 @@ const language_es_es = { "Home": "Inicio", "Search": "Buscar", "Library": "Biblioteca", - "Offline mode, can't play flow or smart track lists.": "Modo sin conexión, no se puede reproducir el flow o las listas de pistas inteligentes.", + "Offline mode, can't play flow or smart track lists.": + "Modo sin conexión, no se puede reproducir el flow o las listas de pistas inteligentes.", "Added to library": "Agregado a la biblioteca", "Download": "Descargar", "Disk": "Disco", @@ -27,30 +28,39 @@ const language_es_es = { "Post processing...": "Post procesamiento...", "Done": "Hecho", "Delete": "Eliminar", - "Are you sure you want to delete this download?": "¿Estás seguro de que quieres borrar esta descarga?", + "Are you sure you want to delete this download?": + "¿Estás seguro de que quieres borrar esta descarga?", "Cancel": "Cancelar", "Downloads": "Descargas", "Clear queue": "Limpiar la cola", - "This won't delete currently downloading item": "Esto no borrará el elemento que se está descargando actualmente", - "Are you sure you want to delete all queued downloads?": "¿Estás seguro de que quieres borrar todas las descargas en cola?", + "This won't delete currently downloading item": + "Esto no borrará el elemento que se está descargando actualmente", + "Are you sure you want to delete all queued downloads?": + "¿Estás seguro de que quieres borrar todas las descargas en cola?", "Clear downloads history": "Borrar el historial de descargas", - "WARNING: This will only clear non-offline (external downloads)": "ADVERTENCIA: Esto sólo borrará las descargas que no están en modo sin conexión (descargas externas).", - "Please check your connection and try again later...": "Por favor, compruebe su conexión y vuelva a intentarlo más tarde...", + "WARNING: This will only clear non-offline (external downloads)": + "ADVERTENCIA: Esto sólo borrará las descargas que no están en modo sin conexión (descargas externas).", + "Please check your connection and try again later...": + "Por favor, compruebe su conexión y vuelva a intentarlo más tarde...", "Show more": "Mostrar más", "Importer": "Importador", - "Currently supporting only Spotify, with 100 tracks limit": "Actualmente sólo se soporta Spotify, con un límite de 100 pistas", + "Currently supporting only Spotify, with 100 tracks limit": + "Actualmente sólo se soporta Spotify, con un límite de 100 pistas", "Due to API limitations": "Debido a limitaciones de API", - "Enter your playlist link below": "Ingrese el enlace de su lista de reproducción a continuación", + "Enter your playlist link below": + "Ingrese el enlace de su lista de reproducción a continuación", "Error loading URL!": "¡Error al cargar la URL!", "Convert": "Convertir", "Download only": "Sólo descargar", - "Downloading is currently stopped, click here to resume.": "La descarga está actualmente detenida, haga clic aquí para reanudarla.", + "Downloading is currently stopped, click here to resume.": + "La descarga está actualmente detenida, haga clic aquí para reanudarla.", "Tracks": "Pistas", "Albums": "Álbumes", "Artists": "Artistas", "Playlists": "Listas de reproducción", "Import": "Importar", - "Import playlists from Spotify": "Importar listas de reproducción de Spotify", + "Import playlists from Spotify": + "Importar listas de reproducción de Spotify", "Statistics": "Estadísticas", "Offline tracks": "Pistas sin conexión", "Offline albums": "Álbumes sin conexión", @@ -61,20 +71,25 @@ const language_es_es = { "Favorites": "Favoritas", "All offline tracks": "Todas las pistas fuera de línea", "Create new playlist": "Crear nueva lista de reproducción", - "Cannot create playlists in offline mode": "No se pueden crear listas de reproducción en el modo sin conexión", + "Cannot create playlists in offline mode": + "No se pueden crear listas de reproducción en el modo sin conexión", "Error": "Error", - "Error logging in! Please check your token and internet connection and try again.": "¡Error al iniciar la sesión! Por favor, compruebe su token y su conexión a Internet e inténtelo de nuevo.", + "Error logging in! Please check your token and internet connection and try again.": + "¡Error al iniciar la sesión! Por favor, compruebe su token y su conexión a Internet e inténtelo de nuevo.", "Dismiss": "Descartar", "Welcome to": "Bienvenido a", - "Please login using your Deezer account.": "Por favor, inicie sesión con su cuenta de Deezer.", + "Please login using your Deezer account.": + "Por favor, inicie sesión con su cuenta de Deezer.", "Login using browser": "Ingresar usando el navegador", "Login using token": "Ingresar usando token", "Enter ARL": "Ingrese ARL", "Token (ARL)": "Token (ARL)", "Save": "Guardar", - "If you don't have account, you can register on deezer.com for free.": "Si no tienes una cuenta, puedes registrarte en deezer.com de forma gratuita.", + "If you don't have account, you can register on deezer.com for free.": + "Si no tienes una cuenta, puedes registrarte en deezer.com de forma gratuita.", "Open in browser": "Abrir en el navegador", - "By using this app, you don't agree with the Deezer ToS": "Al usar esta aplicación, no está de acuerdo con las Condiciones de servicio de Deezer", + "By using this app, you don't agree with the Deezer ToS": + "Al usar esta aplicación, no está de acuerdo con las Condiciones de servicio de Deezer", "Play next": "Reproducir siguiente", "Add to queue": "Añadir a la cola", "Add track to favorites": "Agregar pista a favoritos", @@ -95,7 +110,8 @@ const language_es_es = { "Add to favorites": "Agregar a favoritos", "Remove from library": "Eliminar de la biblioteca", "Add playlist to library": "Agregar lista de reproducción a la biblioteca", - "Added playlist to library": "Lista de reproducción agregada a la biblioteca", + "Added playlist to library": + "Lista de reproducción agregada a la biblioteca", "Make playlist offline": "Hacer lista de reproducción sin conexión", "Download playlist": "Descargar lista de reproducción", "Create playlist": "Crear lista de reproducción", @@ -126,21 +142,25 @@ const language_es_es = { "Deezer (Dark)": "Deezer (oscuro)", "Primary color": "Color primario", "Selected color": "Color seleccionado", - "Use album art primary color": "Usar el color primario de la carátula del álbum", + "Use album art primary color": + "Usar el color primario de la carátula del álbum", "Warning: might be buggy": "Advertencia: podría tener errores", "Mobile streaming": "Transmisión móvil", "Wifi streaming": "Transmisión WiFi", "External downloads": "Descargas externas", "Content language": "Lenguaje del contenido", - "Not app language, used in headers. Now": "No es un lenguaje de la aplicación, se usa en los encabezados. Ahora", + "Not app language, used in headers. Now": + "No es un lenguaje de la aplicación, se usa en los encabezados. Ahora", "Select language": "Seleccione el idioma", "Content country": "País del contenido", "Country used in headers. Now": "País utilizado en los encabezados. Ahora", "Log tracks": "Seguimiento de las pistas", - "Send track listen logs to Deezer, enable it for features like Flow to work properly": "Envía los registros de escucha de las pistas a Deezer, habilítalo para que funciones como Flow funcionen correctamente", + "Send track listen logs to Deezer, enable it for features like Flow to work properly": + "Envía los registros de escucha de las pistas a Deezer, habilítalo para que funciones como Flow funcionen correctamente", "Offline mode": "Modo sin conexión", "Will be overwritten on start.": "Se sobrescribirá al inicio.", - "Error logging in, check your internet connections.": "Error al iniciar sesión, verifique su conexión a internet.", + "Error logging in, check your internet connections.": + "Error al iniciar sesión, verifique su conexión a internet.", "Logging in...": "Ingresando...", "Download path": "Ruta de las descargas", "Downloads naming": "Nombramiento de las descargas", @@ -151,12 +171,15 @@ const language_es_es = { "Create folders for artist": "Crear carpetas por artista", "Create folders for albums": "Crear carpetas por álbumes", "Separate albums by discs": "Separar los álbumes por discos", - "Overwrite already downloaded files": "Sobrescribir los archivos ya descargados", + "Overwrite already downloaded files": + "Sobrescribir los archivos ya descargados", "Copy ARL": "Copiar ARL", - "Copy userToken/ARL Cookie for use in other apps.": "Copia el Token de usuario/Cookie ARL para su uso en otras aplicaciones.", + "Copy userToken/ARL Cookie for use in other apps.": + "Copia el Token de usuario/Cookie ARL para su uso en otras aplicaciones.", "Copied": "Copiado", "Log out": "Cerrar sesión", - "Due to plugin incompatibility, login using browser is unavailable without restart.": "Debido a la incompatibilidad de los plugins, no se puede iniciar la sesión con el navegador sin reiniciar.", + "Due to plugin incompatibility, login using browser is unavailable without restart.": + "Debido a la incompatibilidad de los plugins, no se puede iniciar la sesión con el navegador sin reiniciar.", "(ARL ONLY) Continue": "Continuar (SÓLO ARL)", "Log out & Exit": "Cerrar sesión y salir", "Pick-a-Path": "Escoja una ruta", @@ -164,13 +187,13 @@ const language_es_es = { "Go up": "Subir", "Permission denied": "Permiso denegado", "Language": "Idioma", - "Language changed, please restart Freezer to apply!": "¡El idioma ha cambiado, por favor reinicie Freezer para aplicarlo!", + "Language changed, please restart Freezer to apply!": + "¡El idioma ha cambiado, por favor reinicie Freezer para aplicarlo!", "Importing...": "Importando...", "Radio": "Radio", "Flow": "Flow", - + //0.5.0 Strings: - "Storage permission denied!": "Permiso de almacenamiento denegado!", "Failed": "Fallido", "Queued": "Puesto en cola", @@ -185,20 +208,28 @@ const language_es_es = { "Search or paste URL": "Buscar o pegar URL", "History": "Historial", "Download threads": "Descargas simultáneas", - "Lyrics unavailable, empty or failed to load!": "Letras no disponibles, vacías o no se pudieron cargar!", + "Lyrics unavailable, empty or failed to load!": + "Letras no disponibles, vacías o no se pudieron cargar!", "About": "Acerca de", "Telegram Channel": "Canal de Telegram", "To get latest releases": "Para obtener los últimos lanzamientos", "Official chat": "Chat oficial", "Telegram Group": "Grupo de Telegram", - "Huge thanks to all the contributors! <3": "Muchas gracias a todos los contribuyentes contributors! <3", + "Huge thanks to all the contributors! <3": + "Muchas gracias a todos los contribuyentes contributors! <3", "Edit playlist": "Editar lista de reproducción", "Update": "Actualizar", "Playlist updated!": "Lista de reproducción actualizada!", - "Downloads added!": "Descargas agregadas!" - "Save cover file for every track": "Guarde el archivo de portada para cada pista", + "Downloads added!": "Descargas agregadas!", + "Save cover file for every track": + "Guarde el archivo de portada para cada pista", "Download Log": "Registro de Descarga", "Repository": "Repositorio", - "Source code, report issues there.": "Código fuente, informe de problemas allí." + "Source code, report issues there.": + "Código fuente, informe de problemas allí.", + + //0.5.2 Strings: + "Use system theme": "Usar tema del sistema", + "Light": "blanco" } }; diff --git a/lib/languages/it_it.dart b/lib/languages/it_it.dart index a7ed8e9..a81fef6 100644 --- a/lib/languages/it_it.dart +++ b/lib/languages/it_it.dart @@ -10,7 +10,7 @@ const language_it_it = { "Search": "Cerca", "Library": "Libreria", "Offline mode, can't play flow or smart track lists.": - "Modalità offline, non è possibile riprodurre flow o tracklist smart", + "Modalità offline, non è possibile riprodurre flow o tracklist smart", "Added to library": "Aggiunto alla libreria", "Download": "Scarica", "Disk": "Disco", @@ -29,31 +29,31 @@ const language_it_it = { "Done": "Fatto", "Delete": "Cancellare", "Are you sure you want to delete this download?": - "Sei sicuro di voler cancellare questo download?", + "Sei sicuro di voler cancellare questo download?", "Cancel": "Annulla", "Downloads": "Download", "Clear queue": "Pulisci la coda", "This won't delete currently downloading item": - "Questa azione non cancellerà i download", + "Questa azione non cancellerà i download", "Are you sure you want to delete all queued downloads?": - "Sei sicuro di voler cancellare tutti i download in coda?", + "Sei sicuro di voler cancellare tutti i download in coda?", "Clear downloads history": "Pulisci la cronologia dei download", "WARNING: This will only clear non-offline (external downloads)": - "ATTENZIONE: Questa azione, pulirà solo i files che non sono offline (download esterni)", + "ATTENZIONE: Questa azione, pulirà solo i files che non sono offline (download esterni)", "Please check your connection and try again later...": - "Per favore controlla la tua connessione e riprova più tardi...", + "Per favore controlla la tua connessione e riprova più tardi...", "Show more": "Mostra di più", "Importer": "Importa", "Currently supporting only Spotify, with 100 tracks limit": - "Attualmente supporta solo Spotify, con un limite di 100 brani", + "Attualmente supporta solo Spotify, con un limite di 100 brani", "Due to API limitations": "A causa delle limitazioni delle API", "Enter your playlist link below": - "Inserisci il link della tua playlist qui sotto", + "Inserisci il link della tua playlist qui sotto", "Error loading URL!": "Errore nel caricare l'URL!", "Convert": "Converti", "Download only": "Solo Download", "Downloading is currently stopped, click here to resume.": - "Il download è attualmente interrotto, fare clic qui per riprenderlo.", + "Il download è attualmente interrotto, fare clic qui per riprenderlo.", "Tracks": "Brani", "Albums": "Album", "Artists": "Artisti", @@ -71,24 +71,24 @@ const language_it_it = { "All offline tracks": "Tutte i brani offline", "Create new playlist": "Crea una nuova playlist", "Cannot create playlists in offline mode": - "Impossibile creare playlist in modalità offline", + "Impossibile creare playlist in modalità offline", "Error": "Errore", "Error logging in! Please check your token and internet connection and try again.": - "Errore durante l'accesso! Controlla il token, la tua connessione ad internet e riprova.", + "Errore durante l'accesso! Controlla il token, la tua connessione ad internet e riprova.", "Dismiss": "Chiudi", "Welcome to": "Benvenuto su", "Please login using your Deezer account.": - "Per favore, esegui il login utilizzando il tuo account Deezer.", + "Per favore, esegui il login utilizzando il tuo account Deezer.", "Login using browser": "Login utilizzando il browser", "Login using token": "Login utilizzando il token", "Enter ARL": "Inserisci l'ARL", "Token (ARL)": "Token (ARL)", "Save": "Salva", "If you don't have account, you can register on deezer.com for free.": - "Se non possiedi un account, puoi registrarti sul sito deezer.com gratuitamente.", + "Se non possiedi un account, puoi registrarti sul sito deezer.com gratuitamente.", "Open in browser": "Apri nel browser", "By using this app, you don't agree with the Deezer ToS": - "Utilizzando questa applicazione, non accetti i ToS di Deezer", + "Utilizzando questa applicazione, non accetti i ToS di Deezer", "Play next": "Riproduci subito dopo", "Add to queue": "Aggiungi alla coda", "Add track to favorites": "Aggiungi il brano ai preferiti", @@ -141,24 +141,24 @@ const language_it_it = { "Primary color": "Colore Principale", "Selected color": "Colore Selezionato", "Use album art primary color": - "Usa il colore principale della copertina dell'album", + "Usa il colore principale della copertina dell'album", "Warning: might be buggy": "Attenzione: potrebbe causare problemi", "Mobile streaming": "Streaming con dati", "Wifi streaming": "Streaming con WiFi", "External downloads": "Download esterni", "Content language": "Lingua dei contenuti", "Not app language, used in headers. Now": - "Non la lingua dell'app, utilizzata negli header. Adesso", + "Non la lingua dell'app, utilizzata negli header. Adesso", "Select language": "Seleziona la lingua", "Content country": "Contenuto dal Paese", "Country used in headers. Now": "Paese contenuto negli header. Ora", "Log tracks": "Log delle tracce", "Send track listen logs to Deezer, enable it for features like Flow to work properly": - "Invia i log delle canzioni ascoltate a Deezer, abilitalo affinché features come Flow funzionino correttamente", + "Invia i log delle canzioni ascoltate a Deezer, abilitalo affinché features come Flow funzionino correttamente", "Offline mode": "Modalità Offline", "Will be overwritten on start.": "Sarà sovrascritto all'avvio.", "Error logging in, check your internet connections.": - "Errore durante l'accesso, controlla la tua connessione Internet.", + "Errore durante l'accesso, controlla la tua connessione Internet.", "Logging in...": "Accesso in corso...", "Download path": "Percorso di download", "Downloads naming": "Denominazione dei download", @@ -172,11 +172,11 @@ const language_it_it = { "Overwrite already downloaded files": "Sovrascrivi i file già scaricati", "Copy ARL": "Copia ARL", "Copy userToken/ARL Cookie for use in other apps.": - "Copia userToken / ARL Cookie da utilizzare in altre app.", + "Copia userToken / ARL Cookie da utilizzare in altre app.", "Copied": "Copiato", "Log out": "Disconnettiti", "Due to plugin incompatibility, login using browser is unavailable without restart.": - "A causa dell'incompatibilità del plug-in, l'accesso tramite browser non è disponibile senza riavvio.", + "A causa dell'incompatibilità del plug-in, l'accesso tramite browser non è disponibile senza riavvio.", "(ARL ONLY) Continue": "(SOLO ARL) Continua", "Log out & Exit": "Disconnettiti e Esci", "Pick-a-Path": "Scegli un percorso", @@ -185,14 +185,12 @@ const language_it_it = { "Permission denied": "Permesso negato", "Language": "Lingua", "Language changed, please restart Freezer to apply!": - "Lingua cambiata, riavvia Freezer per applicare la modifica!", + "Lingua cambiata, riavvia Freezer per applicare la modifica!", "Importing...": "Importando...", "Radio": "Radio", "Flow": "Flow", - //0.5.0 Strings: - "Storage permission denied!": "Autorizzazione di archiviazione negata!", "Failed": "Fallito", "Queued": "In coda", @@ -207,22 +205,28 @@ const language_it_it = { "Search or paste URL": "Cerca o incolla l'URL", "History": "Storia", "Download threads": "Download simultanei", - "Lyrics unavailable, empty or failed to load!": "Testi non disponibili, vuoti o caricamento non riuscito!", + "Lyrics unavailable, empty or failed to load!": + "Testi non disponibili, vuoti o caricamento non riuscito!", "About": "Info", "Telegram Channel": "Canale Telegram", "To get latest releases": "Per ottenere le ultime versioni", "Official chat": "Chat ufficiale", "Telegram Group": "Gruppo Telegram", - "Huge thanks to all the contributors! <3": "Un enorme grazie a tutti i collaboratori! <3", + "Huge thanks to all the contributors! <3": + "Un enorme grazie a tutti i collaboratori! <3", "Edit playlist": "Modifica playlist", "Update": "Aggiorna", "Playlist updated!": "Playlist aggiornata!", - "Downloads added!": "Download aggiunti!" - "Save cover file for every track": "Salva la copertina dell'album per ogni traccia", + "Downloads added!": "Download aggiunti!", + "Save cover file for every track": + "Salva la copertina dell'album per ogni traccia", "Download Log": "Download Log", "Repository": "Repository", - "Source code, report issues there.": "Codice sorgente, segnala i problemi lì." - - + "Source code, report issues there.": + "Codice sorgente, segnala i problemi lì.", + + //0.5.2 Strings: + "Use system theme": "Utilizza il tema di sistema", + "Light": "Chiaro" } }; diff --git a/lib/languages/ro_ro.dart b/lib/languages/ro_ro.dart new file mode 100644 index 0000000..619bc64 --- /dev/null +++ b/lib/languages/ro_ro.dart @@ -0,0 +1,230 @@ +/* + +Translated by: MicroMihai + +*/ + +const language_ro_ro = { + "ro_ro": { + "Home": "Home", + "Search": "Căutare", + "Library": "Librărie", + "Offline mode, can't play flow or smart track lists.": + "Mod offline, nu pot reda flow-uri sau liste smart track.", + "Added to library": "Adăugat la librărie", + "Download": "Descărcați", + "Disk": "Disc", + "Offline": "Offline", + "Top Tracks": "Piese Top", + "Show more tracks": "Afișează mai multe piese", + "Top": "Top", + "Top Albums": "Albume Top", + "Show all albums": "Afișează toate albumele", + "Discography": "Discografie", + "Default": "Implicit", + "Reverse": "Invers", + "Alphabetic": "Alfabetic", + "Artist": "Artist", + "Post processing...": "Post procesare...", + "Done": "Gata", + "Delete": "Ștergeți", + "Are you sure you want to delete this download?": + "Ești sigur că vrei să ștergi această descărcare?", + "Cancel": "Anulează", + "Downloads": "Descărcări", + "Clear queue": "Ștergeți coada", + "This won't delete currently downloading item": + "Aceasta nu va șterge elementul care se descarcă acum", + "Are you sure you want to delete all queued downloads?": + "Ești sigur că vrei să ștergi toate descărcările aflate în coadă?", + "Clear downloads history": "Șterge istoricul descărcărilor", + "WARNING: This will only clear non-offline (external downloads)": + "AVERTISMENT: Aceasta va șterge numai non-offline-urile (descărcări externe)", + "Please check your connection and try again later...": + "Vă rugăm să verificați conexiunea și să încercați din nou mai târziu...", + "Show more": "Arată mai multe", + "Importer": "Importator", + "Currently supporting only Spotify, with 100 tracks limit": + "În prezent acceptă doar Spotify, cu limita de 100 de piese", + "Due to API limitations": "Din cauza limitărilor API", + "Enter your playlist link below": "Introduceți linkul playlistului de mai jos", + "Error loading URL!": "Eroare la încărcarea URL-ului!", + "Convert": "Convertiți", + "Download only": "Doar descărcare", + "Downloading is currently stopped, click here to resume.": + "Descărcarea acum este oprită, faceți clic pentru a relua.", + "Tracks": "Piese", + "Albums": "Albume", + "Artists": "Artiști", + "Playlists": "Playlist-uri", + "Import": "Import", + "Import playlists from Spotify": "Importă playlist-uri din Spotify", + "Statistics": "Statistici", + "Offline tracks": "Piese offline", + "Offline albums": "Albume offline", + "Offline playlists": "Playlist-uri offline", + "Offline size": "Dimensiune offline", + "Free space": "Spațiu liber", + "Loved tracks": "Piese favorite", + "Favorites": "Favorite", + "All offline tracks": "Toate piesele offline", + "Create new playlist": "Crează un nou playlist", + "Cannot create playlists in offline mode": + "Nu se pot crea playlist-uri în modul offline", + "Error": "Eroare", + "Error logging in! Please check your token and internet connection and try again.": + "Eroare la conectare! Verificați token-ul și conexiunea la internet și încercați din nou.", + "Dismiss": "Renunță", + "Welcome to": "Bun venit la", + "Please login using your Deezer account.": + "Te rugăm să te conectezi utilizând contul tau Deezer.", + "Login using browser": "Autentificare utilizând browserul", + "Login using token": "Autentificare folosind token-ul", + "Enter ARL": "Introduceți ARL-ul", + "Token (ARL)": "Token (ARL)", + "Save": "Salvează", + "If you don't have account, you can register on deezer.com for free.": + "Dacă nu ai un cont, te poți înregistra gratuit pe deezer.com.", + "Open in browser": "Deschide în browser", + "By using this app, you don't agree with the Deezer ToS": + "Prin utilizarea acestei aplicații, nu sunteți de acord cu Deezer ToS", + "Play next": "Redă urmatorul", + "Add to queue": "Adaugă la coadă", + "Add track to favorites": "Adaugă piesa la favorite", + "Add to playlist": "Adaugă la un playlist", + "Select playlist": "Selectează playlist-ul", + "Track added to": "Piesa a fost adăugată la", + "Remove from playlist": "Șterge din playlist", + "Track removed from": "Piesa a fost eliminată din", + "Remove favorite": "Ștergeți favoritul", + "Track removed from library": "Piesa a fost eliminată din librărie", + "Go to": "Accesați", + "Make offline": "Pune offline", + "Add to library": "Adaugă la librărie", + "Remove album": "Șterge album-ul", + "Album removed": "Album-ul a fost șters", + "Remove from favorites": "Șterge din favorite", + "Artist removed from library": "Artist șters din librărie", + "Add to favorites": "Adaugă la favorite", + "Remove from library": "Șterge din librărie", + "Add playlist to library": "Adaugă playlist-ul la librărie", + "Added playlist to library": "Playlist-ul a fost adăugat la librărie", + "Make playlist offline": "Pune playlist-ul offline", + "Download playlist": "Descarcă playlist-ul", + "Create playlist": "Crează un playlist", + "Title": "Titlu", + "Description": "Descriere", + "Private": "Privat", + "Collaborative": "Colaborativ", + "Create": "Create", + "Playlist created!": "Playlist-ul a fost creat!", + "Playing from:": "Redare din:", + "Queue": "Coadă", + "Offline search": "Căutare offline", + "Search Results": "Rezultate găsite", + "No results!": "Nici un rezultat", + "Show all tracks": "Afișează toate piesele", + "Show all playlists": "Afișează toate playlist-urile", + "Settings": "Setări", + "General": "General", + "Appearance": "Aspect", + "Quality": "Calitate", + "Deezer": "Deezer", + "Theme": "Temă", + "Currently": "Acum", + "Select theme": "Alege tema", + "Light (default)": "Aprins (Default)", + "Dark": "Întunecat", + "Black (AMOLED)": "Negru (AMOLED)", + "Deezer (Dark)": "Deezer (Întunecat)", + "Primary color": "Culoare primară", + "Selected color": "Culoarea selectată", + "Use album art primary color": "Utilizați culoarea primară ale album-ului", + "Warning: might be buggy": "Avertisment: ar putea fi cam bug-uit", + "Mobile streaming": "Streaming mobil", + "Wifi streaming": "Streaming Wi-Fi", + "External downloads": "Descărcări externe", + "Content language": "Limbajul conținutului", + "Not app language, used in headers. Now": + "Nu este limba aplicației, folosit în header (titlu). Acum", + "Select language": "Alege o limbă", + "Content country": "Conținutul tării", + "Country used in headers. Now": "Țara este utilizată în header-i (titluri). Acum", + "Log tracks": "Log-ul pieselor", + "Send track listen logs to Deezer, enable it for features like Flow to work properly": + "Trimiteți log-urile de ascultare a pieselor către Deezer, activați-l pentru funcții precum Flow să funcționeze corect", + "Offline mode": "Mod offline", + "Will be overwritten on start.": "Va fi suprascris la început.", + "Error logging in, check your internet connections.": + "Eroare la conectare, verificați conexiunile la internet.", + "Logging in...": "Conectare...", + "Download path": "Calea descărcărilor", + "Downloads naming": "Denumirea descărcărilor", + "Downloaded tracks filename": "Numele pieselor descărcate", + "Valid variables are": "Variabilele valide sunt", + "Reset": "Reset", + "Clear": "Șterge", + "Create folders for artist": "Creați foldere pentru artiști", + "Create folders for albums": "Creați foldere pentru albume", + "Separate albums by discs": "Separează albumele după discuri", + "Overwrite already downloaded files": "Suprascrieți fișierele deja descărcate", + "Copy ARL": "Copiază ARL-ul", + "Copy userToken/ARL Cookie for use in other apps.": + "Copiază userToken-ul/ARL-ul Cookie utilizarea în alte aplicații.", + "Copied": "Copiat", + "Log out": "Deconectază", + "Due to plugin incompatibility, login using browser is unavailable without restart.": + "Din cauza incompatibilității plugin-ului, conectarea utilizând browserul nu este disponibilă fără un restart", + "(ARL ONLY) Continue": "(DOAR ARL) Continuă", + "Log out & Exit": "Deconectează și ieși", + "Pick-a-Path": "Alege o cale", + "Select storage": "Selectează stocarea", + "Go up": "Du-te sus", + "Permission denied": "Permisie refuzată", + "Language": "Limbă", + "Language changed, please restart Freezer to apply!": + "Limba a fost schimbată, restart-ați Freezer pentru a aplica schimbarea!", + "Importing...": "Importând...", + "Radio": "Radio", + "Flow": "Flow", + "Track is not available on Deezer!": "Piesa nu este disponibilă pe Deezer!", + "Failed to download track! Please restart.": "Descărcarea piesei nu a reușit! Restart-ați.", + + //0.5.0 Strings: + "Storage permission denied!": "Permisia de stocare a fost refuzată!", + "Failed": "Eșuat", + "Queued": "În coadă", + //Updated in 0.5.1 - used in context of download: + "External": "Stocare", + //0.5.0 + "Restart failed downloads": "Restart-ați descărcările eșuate", + "Clear failed": "Șterge eșuatele", + "Download Settings": "Descărcați setările", + "Create folder for playlist": "Creați foldere pentru playlist-uri", + "Download .LRC lyrics": "Descărcați versurile .LRC", + "Proxy": "Proxy", + "Not set": "Nu este setat", + "Search or paste URL": "Caută sau pune un URL", + "History": "Istorie", + //Updated 0.5.1 + "Download threads": "Descărcări simultane", + //0.5.0 + "Lyrics unavailable, empty or failed to load!": "Versurile nu sunt disponibile, goale sau au eșuat încărcarea!", + "About": "Despre", + "Telegram Channel": "Canalul Telegram", + "To get latest releases": "Pentru a obține cele mai recente versiuni", + "Official chat": "Chat-ul oficial", + "Telegram Group": "Grupul Telegram", + "Huge thanks to all the contributors! <3": "Mulțumesc frumos tuturor colaboratorilor! <3", + "Edit playlist": "Editați playlist-ul", + "Update": "Actualizează", + "Playlist updated!": "Playlist actualizat!", + "Downloads added!": "Descărcări adăugate!", + + //0.5.1 Strings: + "Save cover file for every track": "Salvează cover-ul pentru fiecare piesă", + "Download Log": "Log-ul descărcării", + "Repository": "Depozit", + "Source code, report issues there.": "Codul sursă (Source code), raportați problemele acolo." + } +}; \ No newline at end of file diff --git a/lib/languages/ru_ru.dart b/lib/languages/ru_ru.dart index 971b104..9db9384 100644 --- a/lib/languages/ru_ru.dart +++ b/lib/languages/ru_ru.dart @@ -1,30 +1,30 @@ /* -Translated by: Annexhack +Translated by: @Orfej */ - const language_ru_ru = { "ru_ru": { "Home": "Главная", "Search": "Поиск", - "Library": "Библиотека", - "Offline mode, can't play flow or smart track lists.": "Офлайн режим, нельзя воспроизводить потоки или умные списки треков.", - "Added to library": "Добавить в библиотеку", + "Library": "Избранное", + "Offline mode, can't play flow or smart track lists.": + "Режим офлайн. Невозможно воспроизвести персональные подборки", + "Added to library": "Добавлено в любимые треки", "Download": "Скачать", "Disk": "Диск", - "Offline": "Скачанные треки", - "Top Tracks": "Лучшие треки", - "Show more tracks": "Показать больше треков", - "Top": "Top", + "Offline": "Загрузить в кеш", + "Top Tracks": "Популярные треки", + "Show more tracks": "Показать все", + "Top": "Лучшее", "Top Albums": "Лучшие альбомы", - "Show all albums": "Показать все альбомы", + "Show all albums": "Показать все", "Discography": "Дискография", "Default": "По умолчанию", - "Reverse": "Обратный", + "Reverse": "В обратном порядке", "Alphabetic": "По алфавиту", "Artist": "Исполнитель", - "Post processing...": "Постобработка...", + "Post processing...": "Делаем магию...", "Done": "Готово", "Delete": "Удалить", "Are you sure you want to delete this download?": @@ -32,152 +32,198 @@ const language_ru_ru = { "Cancel": "Отмена", "Downloads": "Загрузки", "Clear queue": "Очистить очередь", - "This won't delete currently downloading item": "Это не удалит загружаемый в данный момент элемент", + "This won't delete currently downloading item": + "Это не удалит загружаемый сейчас трек", "Are you sure you want to delete all queued downloads?": - "Вы действительно хотите удалить все загрузки в очереди?", + "Вы действительно хотите удалить все запланированные загрузки?", "Clear downloads history": "Очистить историю загрузок", "WARNING: This will only clear non-offline (external downloads)": - "ВНИМАНИЕ: Это очистит только не офлайн(external downloads)", + "Внимание! Это удалит только загрузки (не кеш)", "Please check your connection and try again later...": - "Пожалуйста, проверьте ваше соединение и повторите попытку позже...", + "Проверьте соединение с Интернетом...", "Show more": "Показать больше", - "Importer": "Импортер", - "Currently supporting only Spotify, with 100 tracks limit": "В настоящее время поддерживается только Spotify, с ограничением 100 треков", - "Due to API limitations": "Из-за ограничений API", - "Enter your playlist link below": "Введите ссылку на свой плейлист ниже", - "Error loading URL!": "Ошибка загрузки URL!", - "Convert": "Перерабатывать", - "Download only": "Только скачанные", - "Downloading is currently stopped, click here to resume.": "В настоящее время загрузка остановлена, нажмите здесь, чтобы возобновить.", + "Importer": "Импорт плейлистов", + "Currently supporting only Spotify, with 100 tracks limit": + "В настоящий момент поддерживается только Spotify", + "Due to API limitations": "Можно импортировать не более 100 треков за раз", + "Enter your playlist link below": "Ссылка на плейлист", + "Error loading URL!": "Ошибка загрузки!", + "Convert": "Импортировать", + "Download only": "Скачать", + "Downloading is currently stopped, click here to resume.": + "Загрузка приостановлена, нажмите, чтобы продолжить.", "Tracks": "Треки", "Albums": "Альбомы", "Artists": "Артисты", - "Playlists": "Плейлисты", - "Import": "Импорт", - "Import playlists from Spotify": "Импортировать плейлисты из Spotify", - "Statistics": "Статистика", - "Offline tracks": "Автономные треки", - "Offline albums": "Автономные альбомы", - "Offline playlists": "Офлайн-плейлисты", - "Offline size": "Автономный размер", - "Free space": "Свободное место", + "Playlists": "Playlists", + "Import": "Импорт плейлистов", + "Import playlists from Spotify": "В настоящий момент поддерживается только Spotify", + "Statistics": "Размер кеша", + "Offline tracks": "Треки в кеше:", + "Offline albums": "Альбомы в кеше:", + "Offline playlists": "Плейлисты в кеше:", + "Offline size": "Размер кеша:", + "Free space": "Свободно:", "Loved tracks": "Любимые треки", "Favorites": "Избранное", - "All offline tracks": "Скачанные треки", - "Create new playlist": "Создать новый плейлист", - "Cannot create playlists in offline mode": "Невозможно создавать плейлисты в автономном режиме", + "All offline tracks": "Все треки в кеше", + "Create new playlist": "Новый плейлист", + "Cannot create playlists in offline mode": + "Нельзя создавать плейлисты в режиме офлайн", "Error": "Ошибка", "Error logging in! Please check your token and internet connection and try again.": - "Ошибка входа! Проверьте свой токен и подключение к Интернету и повторите попытку.", - "Dismiss": "Отклонить", + "Ошибка входа. Проверьте корректность ARL и соединение с Интернетом", + "Dismiss": "Я понял", "Welcome to": "Добро пожаловать в", "Please login using your Deezer account.": - "Пожалуйста, войдите, используя свою учетную запись Deezer.", + "Войдите, используя свой аккаунт Deezer.", "Login using browser": "Войти через браузер", - "Login using token": "Войти с помощью токена", + "Login using token": "Войти по токену (ARL)", "Enter ARL": "Введите ARL", "Token (ARL)": "Токен (ARL)", "Save": "Сохранить", "If you don't have account, you can register on deezer.com for free.": - "Если у вас нет учетной записи, вы можете бесплатно зарегистрироваться на deezer.com.", - "Open in browser": "Открыть в браузере", + "Вы можете создать аккаунт на deezer.com. Это бесплатно.", + "Open in browser": "Зарегестрироваться", "By using this app, you don't agree with the Deezer ToS": "Используя это приложение, вы не соглашаетесь с Условиями использования Deezer.", - "Play next": "Следующая песня", + "Play next": "Играть следующим", "Add to queue": "Добавить в очередь", - "Add track to favorites": "Добавить в избранное", + "Add track to favorites": "Добавить в любимые треки", "Add to playlist": "Добавить в плейлист", - "Select playlist": "Выбрать плейлист", + "Select playlist": "Выберите плейлист", "Track added to": "Трек добавлен в", "Remove from playlist": "Удалить из плейлиста", - "Track removed from": "Трек удален из", - "Remove favorite": "Удалить избранное", - "Track removed from library": "Трек удален из библиотеки", + "Track removed from": "Трек удалён из", + "Remove favorite": "Удалить из любимых треков", + "Track removed from library": "Трек удален из Избранного", "Go to": "Перейти к", - "Make offline": "Сделать офлайн", - "Add to library": "Добавить в библиотеку", + "Make offline": "Загрузить в кеш", + "Add to library": "Добавить в Избранное", "Remove album": "Удалить альбом", "Album removed": "Альбом удален", "Remove from favorites": "Удалить из Избранного", - "Artist removed from library": "Артист удален из библиотеки", - "Add to favorites": "Добавить в избранное", - "Remove from library": "Удалить из библиотеки", - "Add playlist to library": "Добавить плейлист в библиотеку", - "Added playlist to library": "Добавлен плейлист в библиотеку", - "Make playlist offline": "Сделать плейлист офлайн", + "Artist removed from library": "Артист удалён", + "Add to favorites": "Добавить в Избранное", + "Remove from library": "Удалить из Избранного", + "Add playlist to library": "Добавить плейлист в Избранное", + "Added playlist to library": "Плейлист добавлен в Избранное", + "Make playlist offline": "Загрузить плейлист в кеш", "Download playlist": "Скачать плейлист", "Create playlist": "Создать плейлист", "Title": "Название", "Description": "Описание", - "Private": "Частный", - "Collaborative": "Совместная", + "Private": "Скрытый", + "Collaborative": "Общего пользования", "Create": "Создать", "Playlist created!": "Плейлист создан!", - "Playing from:": "Играя с:", + "Playing from:": "Сейчас играет:", "Queue": "Очередь", - "Offline search": "Оффлайн поиск", + "Offline search": "Поиск по кешу", "Search Results": "Результаты поиска", - "No results!": "Нет результатов!", + "No results!": "Ничего не найдено!", "Show all tracks": "Показать все треки", "Show all playlists": "Показать все плейлисты", - "Settings": "Настройки", - "General": "Общее", - "Appearance": "Интерфейс", + "Settings": "Настрокий", + "General": "Управление аккаунтом", + "Appearance": "Внешний вид", "Quality": "Качество звука", - "Deezer": "Deezer", + "Deezer": "Взаимодействие с Deezer", "Theme": "Тема", - "Currently": "Выбрана тема", + "Currently": "Используется:", "Select theme": "Выберите тему", "Light (default)": "Светлая (По умолчанию)", - "Dark": "Dark (Темная тема)", + "Dark": "Темная", "Black (AMOLED)": "Черная (AMOLED)", - "Deezer (Dark)": "Deezer (Dark)", - "Primary color": "Основной цвет", - "Selected color": "Выбранный цвет", - "Use album art primary color": "Использовать цвет обложки", - "Warning: might be buggy": "Предупреждение: может быть ошибка", - "Mobile streaming": "Мобильная сеть", - "Wifi streaming": "Wifi сеть", - "External downloads": "Внешние загрузки", - "Content language": "Язык содержания", - "Not app language, used in headers. Now": "Используемый в заголовках. Сейчас", + "Deezer (Dark)": "Deezer (Темная)", + "Primary color": "Цвет акцента", + "Selected color": "Акцент будет выглядеть так", + "Use album art primary color": "Подбирать акцент в цвет обложки", + "Warning: might be buggy": "Осторожно, может вызвать баги", + "Mobile streaming": "Воспроизведение в мобильной сети", + "Wifi streaming": "Воспроизведение по Wi-Fi", + "External downloads": "Скачанные треки", + "Content language": "Язык контента", + "Not app language, used in headers. Now": + "Используется в тегах.", "Select language": "Выберите язык", - "Content country": "Страна содержания", - "Country used in headers. Now": "Страна, используемая в заголовках. Сейчас", - "Log tracks": "Журнал треков", + "Content country": "Страна контента", + "Country used in headers. Now": "Также используется в тегах.", + "Log tracks": "Отправлять статистику", "Send track listen logs to Deezer, enable it for features like Flow to work properly": - "Отправьте журналы прослушивания треков в Deezer, включите его, чтобы такие функции, как Flow, работали правильно", - "Offline mode": "Офлайн режим", - "Will be overwritten on start.": "Будет перезаписан при запуске.", + "Отправлять статистику прослушивания. Необходимо для правильной работы рекомендаций", + "Offline mode": "Режим офлайн", + "Will be overwritten on start.": "Можно слушать только кешированные треки. Работает до перезапуска.", "Error logging in, check your internet connections.": - "Ошибка при входе, проверьте свои интернет-соединения.", - "Logging in...": "Происходит вход в систему...", - "Download path": "Путь сохранения файлов", - "Downloads naming": "Название при скачивании", - "Downloaded tracks filename": "Имя файла загруженных треков", + "Ошибка входа, проверьте соединение с Интернетом", + "Logging in...": "Вход...", + "Download path": "Папка загрузок", + "Downloads naming": "Шаблон для названия", + "Downloaded tracks filename": "Шаблон для названий загруженных треков", "Valid variables are": "Допустимые переменные:", "Reset": "Сброс", "Clear": "Очистить", - "Create folders for artist": "Создавайте папки для исполнителя", - "Create folders for albums": "Создавайте папки для альбомов", - "Separate albums by discs": "Отдельные альбомы по дискам", - "Overwrite already downloaded files": "Перезаписать уже загруженные файлы", - "Copy ARL": "Копировать ARL", + "Create folders for artist": "Создавать папки для исполнителей", + "Create folders for albums": "Создавать папки для альбомов", + "Separate albums by discs": "Разделять альбомы по дискам", + "Overwrite already downloaded files": "Перезаписывать существующие", + "Copy ARL": "Скопировать токен (ARL)", "Copy userToken/ARL Cookie for use in other apps.": - "Копировать userToken/ARL Cookie для использования в других приложениях.", + "Может быть полезно для использования в других приложениях. Не сообщайте токен никому!", "Copied": "Скопировано", "Log out": "Выйти", "Due to plugin incompatibility, login using browser is unavailable without restart.": - "Из-за несовместимости плагинов вход через браузер без перезапуска невозможен.", - "(ARL ONLY) Continue": "(ARL ONLY) Продолжать", - "Log out & Exit": "Выйти и закрыть", - "Pick-a-Path": "Выбери путь", - "Select storage": "Выберите хранилище", - "Go up": "Подниматься", + "После авторизации/выхода через браузер требуется перезапуск.", + "(ARL ONLY) Continue": "(Вход по токену) Выйти", + "Log out & Exit": "Выйти и перезапустить", + "Pick-a-Path": "Выберите папку", + "Select storage": "Выбрерите хранилище", + "Go up": "На уровень вверх", "Permission denied": "Доступ запрещен", - "Language": "Язык приложения", - "Language changed, please restart Freezer to apply!": "Язык изменен, перезапустите Freezer, чтобы применить!", + "Language": "Язык", + "Language changed, please restart Freezer to apply!": + "Язык изменен, перезапустите приложения для применения", "Importing...": "Импорт...", - "Radio": "Радио" + "Radio": "Радио", + "Flow": "Flow", + "Track is not available on Deezer!": "Трек недоступен на Deezer!", + "Failed to download track! Please restart.": "Ошибка заргузки.Попробуйте снова.", + + //0.5.0 Strings: + "Storage permission denied!": "Доступ к хранилищу запрещен!", + "Failed": "Ошибка", + "Queued": "Добавлено в очередь", + //Updated in 0.5.1 - used in context of download: + "External": "Хранилище", + //0.5.0 + "Restart failed downloads": "Перезапустить загрузки с ошибками", + "Clear failed": "Не удалось очистить", + "Download Settings": "Настройки загрузок", + "Create folder for playlist": "Создавать папки для плейлистов", + "Download .LRC lyrics": "Скачивать тексты .LRC", + "Proxy": "Настройки прокси", + "Not set": "Прокси не настроен", + "Search or paste URL": "Введите запрос или ссылку", + "History": "История", + //Updated 0.5.1 + "Download threads": "Количество одновременных загрузок", + //0.5.0 + "Lyrics unavailable, empty or failed to load!": "Ошибка получения текста!", + "About": "О приложении", + "Telegram Channel": "Канал в Telegram", + "To get latest releases": "Здесь можно скачать официальные обновления", + "Official chat": "Группа в Telegram", + "Telegram Group": "Свободное общение о приложении", + "Huge thanks to all the contributors! <3": "Большое спасибо всем участинкам <3", + "Edit playlist": "Изменить плейлист", + "Update": "Обновить", + "Playlist updated!": "Плейлист обновлен!", + "Downloads added!": "Загрузки добавлены!", + + //0.5.1 Strings: + "Save cover file for every track": "Обложки для каждого трека отдельным файлом", + "Download Log": "Лог загрузок (технические данные)", + "Repository": "Репозиторий", + "Source code, report issues there.": "Исходный код, вопросы, предложения." } }; \ No newline at end of file diff --git a/lib/languages/tr_tr.dart b/lib/languages/tr_tr.dart new file mode 100644 index 0000000..57c2cea --- /dev/null +++ b/lib/languages/tr_tr.dart @@ -0,0 +1,231 @@ +/* + +Translated by: HoScHaKaL + +*/ + +const language_tr_tr = { + "tr_tr": { + "Kebab": "Based", + "Home": "Anasayfa", + "Search": "Ara", + "Library": "Kütüphane", + "Offline mode, can't play flow or smart track lists.": + "Çevrimdışı mod, akış veya akıllı parça listelerini çalınamaz.", + "Added to library": "Kütüphaneye eklendi", + "Download": "İndir", + "Disk": "Disk", + "Offline": "Çevrimdışı", + "Top Tracks": "En iyi Parçalar", + "Show more tracks": "Daha fazla parça göster", + "Top": "En iyiler", + "Top Albums": "En iyi Albümler", + "Show all albums": "Tüm albümleri göster", + "Discography": "Diskografi", + "Default": "Varsayılan", + "Reverse": "Tersten", + "Alphabetic": "Alfabetik", + "Artist": "Sanatçı", + "Post processing...": "İşleniyor...", + "Done": "Bitti", + "Delete": "Sil", + "Are you sure you want to delete this download?": + "Bu indirmeyi silmek istediğinizden emin misiniz?", + "Cancel": "İptal", + "Downloads": "İndirilenler", + "Clear queue": "Sırayı temizle", + "This won't delete currently downloading item": + "Bu, şu anda indirilen öğeyi silemez", + "Are you sure you want to delete all queued downloads?": + "Sıradaki tüm indirmeleri silmek istediğinizden emin misiniz?", + "Clear downloads history": "İndirme geçmişini temizle", + "WARNING: This will only clear non-offline (external downloads)": + "UYARI: Bu yalnızca çevrimdışı olmayanları temizler (harici indirmeler)", + "Please check your connection and try again later...": + "Lütfen bağlantınızı kontrol edin ve daha sonra tekrar deneyin ...", + "Show more": "Daha fazla göster", + "Importer": "Importer", + "Currently supporting only Spotify, with 100 tracks limit": + "Şu anda 100 parça sınırıyla yalnızca Spotify'ı destekliyor", + "Due to API limitations": "API sınırlamaları nedeniyle", + "Enter your playlist link below": "Oynatma listesi bağlantınızı aşağıya girin", + "Error loading URL!": "URL yüklenirken hata oluştu!", + "Convert": "Dönüştür", + "Download only": "Sadece indir", + "Downloading is currently stopped, click here to resume.": + "İndirme durduruldu , devam etmek için tıklayın.", + "Tracks": "Parçalar", + "Albums": "Albümler", + "Artists": "Sanatçılar", + "Playlists": "Oynatma listeleri", + "Import": "İçe Aktar", + "Import playlists from Spotify": "Spotify'dan çalma listelerini içe aktarın", + "Statistics": "İstatistikler", + "Offline tracks": "Çevrimdışı parçalar", + "Offline albums": "Çevrimdışı albümler", + "Offline playlists": "Çevrimdışı oynatma listeleri", + "Offline size": "Çevrimdışı boyut", + "Free space": "Boş alan", + "Loved tracks": "Sevilen parçalar", + "Favorites": "Favoriler", + "All offline tracks": "Tüm çevrimdışı parçalar", + "Create new playlist": "Yeni oynatma listesi oluştur", + "Cannot create playlists in offline mode": + "Çevrimdışı modda oynatma listeleri oluşturulamaz", + "Error": "Hata", + "Error logging in! Please check your token and internet connection and try again.": + "Oturum açma hatası! Lütfen tokeninizi ve internet bağlantınızı kontrol edin ve tekrar deneyin.", + "Dismiss": "Reddet", + "Welcome to": "Hoşgeldiniz", + "Please login using your Deezer account.": + "Lütfen Deezer hesabınızı kullanarak giriş yapın.", + "Login using browser": "Tarayıcı kullanarak giriş yapın", + "Login using token": "Token kullanarak giriş yap", + "Enter ARL": "ARL girin", + "Token (ARL)": "Token (ARL)", + "Save": "Kaydet", + "If you don't have account, you can register on deezer.com for free.": + "Hesabınız yoksa deezer.com'a ücretsiz kayıt olabilirsiniz.", + "Open in browser": "Tarayıcıda aç", + "By using this app, you don't agree with the Deezer ToS": + "Bu uygulamayı kullanarak Deezer Hizmet Şartları'nı kabul etmiyorsunuz", + "Play next": "Sonrakini çal", + "Add to queue": "Sıraya ekle", + "Add track to favorites": "Favorilere parça ekle", + "Add to playlist": "Oynatma listesine ekle", + "Select playlist": "Oynatma listesi seçin", + "Track added to": "Parça şuraya eklendi", + "Remove from playlist": "Oynatma listesinden kaldır", + "Track removed from": "Parça şuradan kaldırıldı", + "Remove favorite": "Favoriyi kaldır", + "Track removed from library": "Parça kütüphaneden kaldırıldı", + "Go to": "Git", + "Make offline": "Çevrimdışı yap", + "Add to library": "Kütüphaneye ekle", + "Remove album": "Albümü kaldır", + "Album removed": "Albüm kaldırıldı", + "Remove from favorites": "Favorilerden çıkar", + "Artist removed from library": "Sanatçı kütüphaneden kaldırıldı", + "Add to favorites": "Favorilere ekle", + "Remove from library": "Kütüphaneden kaldır", + "Add playlist to library": "Oynatma listesini kütüphaneye ekleyin", + "Added playlist to library": "Kütüphaneye oynatma listesi eklendi", + "Make playlist offline": "Oynatma listesini çevrimdışı yapın", + "Download playlist": "Oynatma listesini indirin", + "Create playlist": "Oynatma listesi oluştur", + "Title": "Başlık", + "Description": "Açıklama", + "Private": "Özel", + "Collaborative": "İşbirlikçi", + "Create": "Oluştur", + "Playlist created!": "Oynatma listesi oluşturuldu!", + "Playing from:": "Şuradan oynatılıyor:", + "Queue": "Kuyruk", + "Offline search": "Offline search", + "Search Results": "Arama Sonuçları", + "No results!": "Sonuç yok!", + "Show all tracks": "Tüm parçaları göster", + "Show all playlists": "Tüm oynatma listelerini göster", + "Settings": "Ayarlar", + "General": "Genel", + "Appearance": "Arayüz", + "Quality": "Kalite", + "Deezer": "Deezer", + "Theme": "Tema", + "Currently": "Şu anda", + "Select theme": "Tema seçin", + "Light (default)": "Light (Varsayılan)", + "Dark": "Dark", + "Black (AMOLED)": "Black (AMOLED)", + "Deezer (Dark)": "Deezer (Dark)", + "Primary color": "Ana renk", + "Selected color": "Seçilen renk", + "Use album art primary color": "Albüm resmi ana rengini kullan", + "Warning: might be buggy": "Uyarı: hatalı olabilir", + "Mobile streaming": "Mobil akış", + "Wifi streaming": "Wifi akışı", + "External downloads": "Harici indirmeler", + "Content language": "İçerik dili", + "Not app language, used in headers. Now": + "Not app language, used in headers. Now", + "Select language": "Dil seçin", + "Content country": "İçerik ülkesi", + "Country used in headers. Now": "Başlıklarda kullanılan ülke. Şimdi", + "Log tracks": "Log tracks", + "Send track listen logs to Deezer, enable it for features like Flow to work properly": + "Parça dinleme günlüklerini Deezer'a gönderin, Flow gibi özelliklerin düzgün çalışması için etkinleştirin", + "Offline mode": "Çevrimdışı mod", + "Will be overwritten on start.": "Başlangıçta üzerine yazılacak.", + "Error logging in, check your internet connections.": + "Giriş hatası, internet bağlantılarınızı kontrol edin.", + "Logging in...": "Giriş yapılıyor...", + "Download path": "İndirme yolu", + "Downloads naming": "İndirilenler adlandırma", + "Downloaded tracks filename": "İndirilen parçaların dosya adı", + "Valid variables are": "Geçerli değişkenler", + "Reset": "Sıfırla", + "Clear": "Temizle", + "Create folders for artist": "Sanatçı için klasörler oluşturun", + "Create folders for albums": "Albümler için klasörler oluşturun", + "Separate albums by discs": "Albümleri disklere göre ayırın", + "Overwrite already downloaded files": "Zaten indirilmiş dosyaların üzerine yaz", + "Copy ARL": "ARL kopyala", + "Copy userToken/ARL Cookie for use in other apps.": + "Diğer uygulamalarda kullanmak için userToken / ARL Cookie'yi kopyalayın.", + "Copied": "Kopyalandı", + "Log out": "Çıkış yap", + "Due to plugin incompatibility, login using browser is unavailable without restart.": + "Eklenti uyumsuzluğu nedeniyle, yeniden başlatmadan tarayıcı kullanarak oturum açılamaz.", + "(ARL ONLY) Continue": "(SADECE ARL) Devam et", + "Log out & Exit": "Çıkış yap & Çık", + "Pick-a-Path": "Konum seç", + "Select storage": "Depolama seç", + "Go up": "Yukarı git", + "Permission denied": "İzin reddedildi", + "Language": "Dil", + "Language changed, please restart Freezer to apply!": + "Dil değişti,değişiklik için Freezeri yeniden başlatın!", + "Importing...": "İçe aktarılıyor...", + "Radio": "Radyo", + "Flow": "Flow", + "Track is not available on Deezer!": "Parça Deezer'da mevcut değil!", + "Failed to download track! Please restart.": "Parça indirilemedi! Lütfen yeniden başlat.", + + //0.5.0 Strings: + "Storage permission denied!": "Depolama izni reddedildi!", + "Failed": "Başarısız", + "Queued": "Sıraya alındı", + //Updated in 0.5.1 - used in context of download: + "External": "Storage", + //0.5.0 + "Restart failed downloads": "Başarısız indirmeleri yeniden başlatın", + "Clear failed": "Silinemedi", + "Download Settings": "İndirme Ayarları", + "Create folder for playlist": "Oynatma listesi için klasör oluştur", + "Download .LRC lyrics": ".LRC şarkı sözlerini indir", + "Proxy": "Proxy", + "Not set": "Ayarlanmadı", + "Search or paste URL": "Arayın veya URL yapıştırın", + "History": "Geçmiş", + //Updated 0.5.1 + "Download threads": "Eşzamanlı indirmeler", + //0.5.0 + "Lyrics unavailable, empty or failed to load!": "Sözler mevcut değil, boş veya yüklenemedi!", + "About": "Hakkında", + "Telegram Channel": "Telegram Kanalı", + "To get latest releases": "En son sürümleri almak için", + "Official chat": "Resmi sohbet", + "Telegram Group": "Telegram Grubu", + "Huge thanks to all the contributors! <3": "Katkıda bulunanlara çok teşekkürler! <3", + "Edit playlist": "Oynatma listesini düzenleyin", + "Update": "Güncelle", + "Playlist updated!": "Oynatma listesi güncellendi!", + "Downloads added!": "İndirmeler eklendi!", + + //0.5.1 Strings: + "Save cover file for every track": "Her parça için kapak dosyasını kaydedin", + "Download Log": "İndirme Kayıtları", + "Repository": "Depo", + "Source code, report issues there.": "Kaynak kodu, sorunları bildirin" + } +}; \ No newline at end of file diff --git a/lib/settings.dart b/lib/settings.dart index dc1e359..843da70 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -1,6 +1,5 @@ -import 'dart:async'; - import 'package:audio_service/audio_service.dart'; +import 'package:flutter/scheduler.dart'; import 'package:freezer/api/download.dart'; import 'package:freezer/main.dart'; import 'package:freezer/ui/cached_image.dart'; @@ -12,6 +11,7 @@ import 'package:flutter/material.dart'; import 'dart:io'; import 'dart:convert'; +import 'dart:async'; part 'settings.g.dart'; @@ -62,8 +62,10 @@ class Settings { bool trackCover; //Appearance - @JsonKey(defaultValue: Themes.Light) + @JsonKey(defaultValue: Themes.Dark) Themes theme; + @JsonKey(defaultValue: false) + bool useSystemTheme; //Colors @JsonKey(toJson: _colorToJson, fromJson: _colorFromJson) @@ -76,7 +78,6 @@ class Settings { bool useArtColor = false; StreamSubscription _useArtColorSub; - //Deezer @JsonKey(defaultValue: 'en') String deezerLanguage; @@ -89,63 +90,18 @@ class Settings { Settings({this.downloadPath, this.arl}); - static const deezerBg = Color(0xFF1F1A16); - static const font = 'MabryPro'; ThemeData get themeData { - switch (theme??Themes.Light) { - case Themes.Light: - return ThemeData( - fontFamily: font, - primaryColor: primaryColor, - accentColor: primaryColor, - sliderTheme: _sliderTheme, - toggleableActiveColor: primaryColor, - bottomAppBarColor: Color(0xfff7f7f7) - ); - case Themes.Dark: - return ThemeData( - fontFamily: font, - brightness: Brightness.dark, - primaryColor: primaryColor, - accentColor: primaryColor, - sliderTheme: _sliderTheme, - toggleableActiveColor: primaryColor, - ); - case Themes.Deezer: - return ThemeData( - fontFamily: font, - brightness: Brightness.dark, - primaryColor: primaryColor, - accentColor: primaryColor, - sliderTheme: _sliderTheme, - toggleableActiveColor: primaryColor, - backgroundColor: deezerBg, - scaffoldBackgroundColor: deezerBg, - bottomAppBarColor: deezerBg, - dialogBackgroundColor: deezerBg, - bottomSheetTheme: BottomSheetThemeData( - backgroundColor: deezerBg - ), - cardColor: deezerBg - ); - case Themes.Black: - return ThemeData( - fontFamily: font, - brightness: Brightness.dark, - primaryColor: primaryColor, - accentColor: primaryColor, - backgroundColor: Colors.black, - scaffoldBackgroundColor: Colors.black, - bottomAppBarColor: Colors.black, - dialogBackgroundColor: Colors.black, - sliderTheme: _sliderTheme, - toggleableActiveColor: primaryColor, - bottomSheetTheme: BottomSheetThemeData( - backgroundColor: Colors.black - ) - ); + //System theme + if (useSystemTheme) { + if (SchedulerBinding.instance.window.platformBrightness == Brightness.light) { + return _themeData[Themes.Light]; + } else { + if (theme == Themes.Light) return _themeData[Themes.Dark]; + return _themeData[theme]; + } } - return ThemeData(); + //Theme + return _themeData[theme]??ThemeData(); } //JSON to forward into download service @@ -154,7 +110,8 @@ class Settings { "downloadThreads": downloadThreads, "overwriteDownload": overwriteDownload, "downloadLyrics": downloadLyrics, - "trackCover": trackCover + "trackCover": trackCover, + "arl": arl }; } @@ -221,6 +178,57 @@ class Settings { return 8; //default } + static const deezerBg = Color(0xFF1F1A16); + static const font = 'MabryPro'; + Map get _themeData => { + Themes.Light: ThemeData( + fontFamily: font, + primaryColor: primaryColor, + accentColor: primaryColor, + sliderTheme: _sliderTheme, + toggleableActiveColor: primaryColor, + bottomAppBarColor: Color(0xfff7f7f7) + ), + Themes.Dark: ThemeData( + fontFamily: font, + brightness: Brightness.dark, + primaryColor: primaryColor, + accentColor: primaryColor, + sliderTheme: _sliderTheme, + toggleableActiveColor: primaryColor, + ), + Themes.Deezer: ThemeData( + fontFamily: font, + brightness: Brightness.dark, + primaryColor: primaryColor, + accentColor: primaryColor, + sliderTheme: _sliderTheme, + toggleableActiveColor: primaryColor, + backgroundColor: deezerBg, + scaffoldBackgroundColor: deezerBg, + bottomAppBarColor: deezerBg, + dialogBackgroundColor: deezerBg, + bottomSheetTheme: BottomSheetThemeData( + backgroundColor: deezerBg + ), + cardColor: deezerBg + ), + Themes.Black: ThemeData( + fontFamily: font, + brightness: Brightness.dark, + primaryColor: primaryColor, + accentColor: primaryColor, + backgroundColor: Colors.black, + scaffoldBackgroundColor: Colors.black, + bottomAppBarColor: Colors.black, + dialogBackgroundColor: Colors.black, + sliderTheme: _sliderTheme, + toggleableActiveColor: primaryColor, + bottomSheetTheme: BottomSheetThemeData( + backgroundColor: Colors.black + )) + }; + Future getPath() async => p.join((await getApplicationDocumentsDirectory()).path, 'settings.json'); //JSON diff --git a/lib/settings.g.dart b/lib/settings.g.dart index c2f1274..f3e0ff0 100644 --- a/lib/settings.g.dart +++ b/lib/settings.g.dart @@ -35,7 +35,8 @@ Settings _$SettingsFromJson(Map json) { ..downloadLyrics = json['downloadLyrics'] as bool ?? true ..trackCover = json['trackCover'] as bool ?? false ..theme = - _$enumDecodeNullable(_$ThemesEnumMap, json['theme']) ?? Themes.Light + _$enumDecodeNullable(_$ThemesEnumMap, json['theme']) ?? Themes.Dark + ..useSystemTheme = json['useSystemTheme'] as bool ?? false ..primaryColor = Settings._colorFromJson(json['primaryColor'] as int) ..useArtColor = json['useArtColor'] as bool ?? false ..deezerLanguage = json['deezerLanguage'] as String ?? 'en' @@ -62,6 +63,7 @@ Map _$SettingsToJson(Settings instance) => { 'downloadLyrics': instance.downloadLyrics, 'trackCover': instance.trackCover, 'theme': _$ThemesEnumMap[instance.theme], + 'useSystemTheme': instance.useSystemTheme, 'primaryColor': Settings._colorToJson(instance.primaryColor), 'useArtColor': instance.useArtColor, 'deezerLanguage': instance.deezerLanguage, diff --git a/lib/translations.i18n.dart b/lib/translations.i18n.dart index 0f7bd26..1e1bb0b 100644 --- a/lib/translations.i18n.dart +++ b/lib/translations.i18n.dart @@ -11,7 +11,9 @@ import 'package:freezer/languages/hr_hr.dart'; import 'package:freezer/languages/it_it.dart'; import 'package:freezer/languages/ko_ko.dart'; import 'package:freezer/languages/pt_br.dart'; +import 'package:freezer/languages/ro_ro.dart'; import 'package:freezer/languages/ru_ru.dart'; +import 'package:freezer/languages/tr_tr.dart'; import 'package:i18n_extension/i18n_extension.dart'; const supportedLocales = [ @@ -27,6 +29,8 @@ const supportedLocales = [ const Locale('ko', 'KO'), const Locale('fr', 'FR'), const Locale('he', 'IL'), + const Locale('tr', 'TR'), + const Locale('ro', 'RO'), const Locale('fil', 'PH') ]; @@ -34,7 +38,7 @@ extension Localization on String { static var _t = Translations.byLocale("en_US") + language_en_us + language_ar_ar + language_pt_br + language_it_it + language_de_de + language_ru_ru + language_fil_ph + language_es_es + language_el_gr + language_hr_hr + language_ko_ko + language_fr_fr + - language_he_il; + language_he_il + language_tr_tr + language_ro_ro; String get i18n => localize(this, _t); } diff --git a/lib/ui/downloads_screen.dart b/lib/ui/downloads_screen.dart index da4091d..3000f5a 100644 --- a/lib/ui/downloads_screen.dart +++ b/lib/ui/downloads_screen.dart @@ -289,7 +289,7 @@ class DownloadTile extends StatelessWidget { ListTile( title: Text(download.title), leading: CachedImage(url: download.image), - subtitle: Text(subtitle()), + subtitle: Text(subtitle(), maxLines: 1, overflow: TextOverflow.ellipsis), trailing: trailing(), onTap: () => onClick(context), ), diff --git a/lib/ui/login_screen.dart b/lib/ui/login_screen.dart index 1cea990..8b5fcaa 100644 --- a/lib/ui/login_screen.dart +++ b/lib/ui/login_screen.dart @@ -239,7 +239,7 @@ class LoginBrowser extends StatelessWidget { onLoadStart: (InAppWebViewController controller, String url) async { //Offers URL - if (url.contains('/offers')) { + if (!url.contains('/login') && !url.contains('/register')) { controller.evaluateJavascript(source: 'window.location.href = "/open_app"'); } diff --git a/lib/ui/settings_screen.dart b/lib/ui/settings_screen.dart index 496f566..751fe85 100644 --- a/lib/ui/settings_screen.dart +++ b/lib/ui/settings_screen.dart @@ -44,8 +44,9 @@ class _SettingsScreenState extends State { List> _l = supportedLocales.map>((l) { Map _lang = defaultLanguagesList.firstWhere((lang) => lang['isoCode'] == l.languageCode); return { - 'name': _lang['name'] + ' (${l.toString()})', - 'isoCode': _lang['isoCode'] + 'name': _lang['name'], + 'isoCode': _lang['isoCode'], + 'locale': l.toString() }; }).toList(); return _l; @@ -101,33 +102,37 @@ class _SettingsScreenState extends State { onTap: () { showDialog( context: context, - builder: (context) => LanguagePickerDialog( - titlePadding: EdgeInsets.all(8.0), + builder: (context) => SimpleDialog( title: Text('Select language'.i18n), - isSearchable: false, - languagesList: _languages(), - onValuePicked: (Language l) async { - setState(() { - Locale locale = supportedLocales.firstWhere((_l) => _l.languageCode == l.isoCode); - settings.language = locale.toString(); - }); - await settings.save(); - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text('Language'.i18n), - content: Text('Language changed, please restart Freezer to apply!'.i18n), - actions: [ - FlatButton( - child: Text('OK'), - onPressed: () => Navigator.of(context).pop(), - ) - ], + children: List.generate(_languages().length, (int i) { + Map l = _languages()[i]; + return ListTile( + title: Text(l['name']), + subtitle: Text(l['locale']), + onTap: () async { + setState(() => settings.language = l['locale']); + await settings.save(); + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text('Language'.i18n), + content: Text('Language changed, please restart Freezer to apply!'.i18n), + actions: [ + FlatButton( + child: Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }, + ) + ], + ); + } ); - } + }, ); - }, + }) ) ); }, @@ -173,7 +178,7 @@ class _AppearanceSettingsState extends State { title: Text('Select theme'.i18n), children: [ SimpleDialogOption( - child: Text('Light (default)'.i18n), + child: Text('Light'.i18n), onPressed: () { setState(() => settings.theme = Themes.Light); settings.save(); @@ -214,6 +219,22 @@ class _AppearanceSettingsState extends State { ); }, ), + ListTile( + title: Text('Use system theme'.i18n), + leading: Container( + width: 30.0, + child: Checkbox( + value: settings.useSystemTheme, + onChanged: (bool v) async { + setState(() { + settings.useSystemTheme = v; + }); + updateTheme(); + await settings.save(); + }, + ), + ), + ), ListTile( title: Text('Primary color'.i18n), leading: Icon(Icons.format_paint), @@ -1033,14 +1054,16 @@ class _CreditsScreenState extends State { ['Markus', 'German'], ['Andrea', 'Italian'], ['Diego Hiro', 'Portuguese'], - ['Annexhack', 'Russian'], + ['Orfej', 'Russian'], ['Chino Pacia', 'Filipino'], ['ArcherDelta & PetFix', 'Spanish'], ['Shazzaam', 'Croatian'], ['VIRGIN_KLM', 'Greek'], ['koreezzz', 'Korean'], ['Fwwwwwwwwwweze', 'French'], - ['kobyrevah', 'Hebrew'] + ['kobyrevah', 'Hebrew'], + ['HoScHaKaL', 'Turkish'], + ['MicroMihai', 'Romanian'] ]; @override diff --git a/pubspec.yaml b/pubspec.yaml index 37ba240..25b2434 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.5.1+1 +version: 0.5.2+1 environment: sdk: ">=2.8.0 <3.0.0"