diff --git a/lib/app.dart b/lib/app.dart index d5eb8e3..0908726 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -16,6 +16,7 @@ import 'pantallas/pantalla_alarmas.dart'; import 'pantallas/pantalla_alarma_sonando.dart'; import 'pantallas/pantalla_bienvenida.dart'; import 'pantallas/pantalla_inicio.dart'; +import 'pantallas/pantalla_tutorial_ayuda.dart'; import 'pantallas/pantalla_buscar.dart'; import 'pantallas/pantalla_favoritos.dart'; import 'pantallas/pantalla_ajustes.dart'; @@ -281,10 +282,20 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> // pre-existing PluriOnboardingDialog is an unrelated "what's new"/help // modal that keeps its own independent per-version due-or-not logic, // completely unchanged by this sequencing. + // + // The 9-screen help/tutorial carousel (PantallaTutorialAyuda) runs + // BETWEEN the two: after the welcome screen (fresh installs only) and + // before the what's-new dialog. Unlike the welcome screen, the tutorial + // shows once to EVERY install -- fresh AND existing -- via its own plain + // one-time flag (ServicioTutorialAyuda), which is what makes an + // already-installed app show it once after updating to this version. Future _mostrarFlujoPrimerLanzamiento() async { if (mounted) { await PantallaBienvenida.mostrarSiProcede(context); } + if (mounted) { + await PantallaTutorialAyuda.mostrarSiProcede(context); + } await _mostrarOnboardingInicial(); } diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index ba591d7..7de8683 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -604,7 +604,27 @@ "endLabel": "النهاية", "equalizerDisable": "تعطيل المعادل", "helpTitle": "المساعدة والشرح", - "helpSubtitle": "راجع ميزات PluriWave والنصائح والمستجدات.", + "helpSubtitle": "9 شاشات · شاهده مجددًا متى شئت", + "tutorialSkipAction": "تخطي", + "tutorialNextAction": "التالي", + "tutorialPage1Headline": "احفظ محطاتك ونظّمها في مجموعات", + "tutorialPage1Body": "اضغط على أيقونة القلب لحفظ محطة. في «محطاتك» يمكنك إنشاء مجموعات مثل «كل صباح» أو «السيارة» وإعادة ترتيبها بالسحب.", + "tutorialPage2Headline": "معادل صوت عام وآخر لكل محطة", + "tutorialPage2Body": "من الإعدادات تحدد المعادل الصوتي العام. ومن تشغيل محطة معينة يمكنك ضبط إعداد خاص بها، له الأولوية على الإعداد العام.", + "tutorialPage3Headline": "سجّل ما تستمع إليه", + "tutorialPage3Body": "من شريط أدوات المشغل، يحفظ زر «تسجيل» البث الأصلي. ستجد تسجيلاتك في الإعدادات › التسجيلات.", + "tutorialPage4Headline": "منبهات تتكيّف معك", + "tutorialPage4Body": "استيقظ على محطتك المفضلة، وأجّل المنبه 3 أو 5 أو 10 دقائق، وأضف فترات إجازة ليتخطى بعض المنبهات نفسه تلقائيًا.", + "tutorialPage5Headline": "محطاتك المفضلة، في السيارة أيضًا", + "tutorialPage5Body": "اربط هاتفك بـ Android Auto لتجد المفضلة وجميع المحطات ومحطاتك والموسيقى المحلية، بأزرار كبيرة مصممة للقيادة.", + "tutorialPage6Headline": "يعيد الاتصال تلقائيًا", + "tutorialPage6Body": "إذا انقطعت الإشارة، تعيد PluriWave المحاولة تلقائيًا وتستمر في عرض محطاتك المفضلة المحفوظة حتى بدون اتصال.", + "tutorialPage7Headline": "اختر مدة التأجيل", + "tutorialPage7Body": "عند رنين المنبه، لا يوجد خيار تأجيل واحد فقط: تختار 3 أو 5 أو 10 دقائق حسب ما تحتاجه في تلك اللحظة.", + "tutorialPage8Headline": "لم تجدها؟ أضفها بنفسك", + "tutorialPage8Body": "من «محطاتك» ← إضافة محطة مخصصة، الصق رابط بث محطة غير موجودة في نتائج البحث. تُحفظ في «محطاتك»، وتكون متاحة في السيارة أيضًا.", + "tutorialPage9Headline": "تمّ، أصبحت تعرف الأساسيات", + "tutorialPage9BannerBody": "لمشاهدة هذا الشرح مرة أخرى في أي وقت: الإعدادات ← المعلومات ← المساعدة والشرح.", "indefiniteOption": "غير محدد", "invalidNumber": "رقم غير صالح", "nameLabel": "الاسم", diff --git a/lib/l10n/app_bn.arb b/lib/l10n/app_bn.arb index 66eba91..4e5ab6b 100644 --- a/lib/l10n/app_bn.arb +++ b/lib/l10n/app_bn.arb @@ -604,7 +604,27 @@ "endLabel": "শেষ", "equalizerDisable": "ইকুয়ালাইজার বন্ধ করুন", "helpTitle": "সহায়তা ও টিউটোরিয়াল", - "helpSubtitle": "PluriWave-এর ফিচার, টিপস ও নতুন বিষয়গুলো দেখুন।", + "helpSubtitle": "৯টি স্ক্রিন · যখন খুশি আবার দেখুন", + "tutorialSkipAction": "এড়িয়ে যান", + "tutorialNextAction": "পরবর্তী", + "tutorialPage1Headline": "আপনার স্টেশন সংরক্ষণ করুন এবং গ্রুপে ভাগ করুন", + "tutorialPage1Body": "একটি স্টেশন সংরক্ষণ করতে হার্ট আইকনে ট্যাপ করুন। «আপনার স্টেশন»-এ আপনি «প্রতিদিন সকালে» বা «গাড়ি»-এর মতো গ্রুপ তৈরি করতে পারেন এবং টেনে সেগুলোর ক্রম বদলাতে পারেন।", + "tutorialPage2Headline": "একটি সাধারণ ইকুয়ালাইজার, প্রতিটি স্টেশনের জন্য আরেকটি", + "tutorialPage2Body": "সেটিংসে আপনি সাধারণ ইকুয়ালাইজার ঠিক করেন। আর কোনো নির্দিষ্ট স্টেশন চালানোর সময় আপনি সেটির নিজস্ব সেটিং দিতে পারেন, যা সাধারণ সেটিংয়ের চেয়ে অগ্রাধিকার পায়।", + "tutorialPage3Headline": "যা শুনছেন তা রেকর্ড করুন", + "tutorialPage3Body": "প্লেয়ারের টুল ট্রে থেকে «রেকর্ড করুন» মূল স্ট্রিম সংরক্ষণ করে। আপনার রেকর্ডিং পাবেন সেটিংস › রেকর্ডিং-এ।", + "tutorialPage4Headline": "এমন অ্যালার্ম যা আপনার সাথে মানিয়ে নেয়", + "tutorialPage4Body": "আপনার প্রিয় স্টেশনে জেগে উঠুন, ৩, ৫ বা ১০ মিনিট স্নুজ করুন, এবং ছুটির সময়সীমা যোগ করুন যাতে কিছু অ্যালার্ম নিজে থেকেই বাদ পড়ে।", + "tutorialPage5Headline": "আপনার প্রিয়গুলো, গাড়িতেও", + "tutorialPage5Body": "আপনার ফোন Android Auto-এর সাথে সংযুক্ত করুন এবং পাবেন প্রিয়, সব স্টেশন, আপনার স্টেশন এবং আপনার লোকাল মিউজিক, গাড়ি চালানোর উপযোগী বড় বোতামসহ।", + "tutorialPage6Headline": "নিজে থেকেই আবার সংযুক্ত হয়", + "tutorialPage6Body": "সিগন্যাল কেটে গেলে, PluriWave স্বয়ংক্রিয়ভাবে আবার চেষ্টা করে এবং সংযোগ ছাড়াই আপনার সংরক্ষিত প্রিয়গুলো দেখাতে থাকে।", + "tutorialPage7Headline": "কতক্ষণ স্নুজ করবেন তা বেছে নিন", + "tutorialPage7Body": "অ্যালার্ম বাজলে, «স্নুজ»-এর একটিমাত্র বিকল্প নেই: আপনি সেই মুহূর্তে প্রয়োজন অনুযায়ী ৩, ৫ বা ১০ মিনিট বেছে নেন।", + "tutorialPage8Headline": "খুঁজে পাচ্ছেন না? নিজেই যোগ করুন", + "tutorialPage8Body": "«আপনার স্টেশন» → কাস্টম স্টেশন যোগ করুন-এ, খোঁজে না পাওয়া স্টেশনের স্ট্রিম URL পেস্ট করুন। এটি «আপনার স্টেশন»-এ সংরক্ষিত হয় এবং গাড়িতেও পাওয়া যায়।", + "tutorialPage9Headline": "শেষ, এখন আপনি মূল বিষয়গুলো জানেন", + "tutorialPage9BannerBody": "এই টিউটোরিয়ালটি আবার দেখতে: সেটিংস → তথ্য → সহায়তা ও টিউটোরিয়াল।", "indefiniteOption": "অনির্দিষ্ট", "invalidNumber": "অবৈধ সংখ্যা", "nameLabel": "নাম", diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 4e3b18b..6fe80b7 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -604,7 +604,27 @@ "endLabel": "Ende", "equalizerDisable": "Equalizer deaktivieren", "helpTitle": "Hilfe und Tutorial", - "helpSubtitle": "Funktionen, Tipps und Neuigkeiten von PluriWave ansehen.", + "helpSubtitle": "9 Bildschirme · jederzeit erneut ansehen", + "tutorialSkipAction": "Überspringen", + "tutorialNextAction": "Weiter", + "tutorialPage1Headline": "Speichere deine Sender und gruppiere sie", + "tutorialPage1Body": "Tippe auf das Herz, um einen Sender zu speichern. Unter „Deine Sender“ kannst du Gruppen wie „Jeden Morgen“ oder „Auto“ anlegen und sie per Ziehen neu anordnen.", + "tutorialPage2Headline": "Ein Basis-Equalizer und einer pro Sender", + "tutorialPage2Body": "In den Einstellungen legst du den allgemeinen Equalizer fest. Und während der Wiedergabe eines bestimmten Senders kannst du ihm eine eigene Einstellung geben, die Vorrang vor der allgemeinen hat.", + "tutorialPage3Headline": "Nimm auf, was du gerade hörst", + "tutorialPage3Body": "Über die Werkzeugleiste des Players speichert „Aufnehmen“ den Original-Stream. Deine Aufnahmen findest du unter Einstellungen › Aufnahmen.", + "tutorialPage4Headline": "Alarme, die sich dir anpassen", + "tutorialPage4Body": "Wach mit deinem Lieblingssender auf, schlummere 3, 5 oder 10 Minuten weiter und füge Urlaubszeiträume hinzu, damit manche Alarme von selbst ausgesetzt werden.", + "tutorialPage5Headline": "Deine Favoriten, auch im Auto", + "tutorialPage5Body": "Verbinde dein Handy mit Android Auto und finde Favoriten, Alle Sender, Deine Sender und deine lokale Musik, mit großen, fürs Fahren gemachten Tasten.", + "tutorialPage6Headline": "Verbindet sich von selbst neu", + "tutorialPage6Body": "Bricht das Signal ab, versucht PluriWave automatisch erneut und zeigt weiterhin deine gespeicherten Favoriten, auch ohne Verbindung.", + "tutorialPage7Headline": "Wähle, wie lange du schlummerst", + "tutorialPage7Body": "Wenn ein Alarm klingelt, gibt es nicht nur ein „Schlummern“: Du wählst 3, 5 oder 10 Minuten, je nachdem, was du gerade brauchst.", + "tutorialPage8Headline": "Findest du ihn nicht? Füge ihn selbst hinzu", + "tutorialPage8Body": "Füge unter „Deine Sender“ → Eigenen Sender hinzufügen die Stream-URL eines Senders ein, der nicht in der Suche auftaucht. Er wird unter „Deine Sender“ gespeichert und ist auch im Auto verfügbar.", + "tutorialPage9Headline": "Fertig, du kennst jetzt das Wichtigste", + "tutorialPage9BannerBody": "Um dieses Tutorial jederzeit erneut anzusehen: Einstellungen → Info → Hilfe und Tutorial.", "indefiniteOption": "Unbegrenzt", "invalidNumber": "Ungültige Zahl", "nameLabel": "Name", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 7a3e740..355e368 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -716,7 +716,27 @@ "endLabel": "End", "equalizerDisable": "Disable equalizer", "helpTitle": "Help and tutorial", - "helpSubtitle": "Review PluriWave features, tips and what’s new.", + "helpSubtitle": "9 screens · watch it again anytime", + "tutorialSkipAction": "Skip", + "tutorialNextAction": "Next", + "tutorialPage1Headline": "Save your stations and group them", + "tutorialPage1Body": "Tap the heart to save a station. In \"Your stations\" you can create groups like \"Every morning\" or \"Car\" and drag to reorder them.", + "tutorialPage2Headline": "One base equalizer, plus one per station", + "tutorialPage2Body": "In Settings you set the general equalizer. And from a specific station's playback screen you can give it its own setting, which overrides the general one.", + "tutorialPage3Headline": "Record what you're listening to", + "tutorialPage3Body": "From the player's tool tray, \"Record\" saves the original stream. Find your recordings under Settings › Recordings.", + "tutorialPage4Headline": "Alarms that adapt to you", + "tutorialPage4Body": "Wake up to your favorite station, snooze for 3, 5, or 10 minutes, and add vacation ranges so some alarms skip themselves.", + "tutorialPage5Headline": "Your favorites, in the car too", + "tutorialPage5Body": "Connect your phone with Android Auto to find Favorites, All stations, Your stations, and your Local Music, with big buttons made for driving.", + "tutorialPage6Headline": "It reconnects on its own", + "tutorialPage6Body": "If the signal drops, PluriWave retries automatically and keeps showing your saved favorites even without a connection.", + "tutorialPage7Headline": "Choose how long to snooze", + "tutorialPage7Body": "When an alarm rings, there's no single \"snooze\": you choose 3, 5, or 10 minutes depending on what you need at that moment.", + "tutorialPage8Headline": "Can't find it? Add it yourself", + "tutorialPage8Body": "In \"Your stations\" → Add custom station, paste the stream URL of a station that isn't in the search results. It's saved under \"Your stations\", also available in the car.", + "tutorialPage9Headline": "Done — now you know the essentials", + "tutorialPage9BannerBody": "To watch this tutorial again anytime: Settings → Information → Help and tutorial.", "indefiniteOption": "Indefinite", "invalidNumber": "Invalid number", "nameLabel": "Name", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 696c698..df3c63a 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -672,7 +672,27 @@ "endLabel": "Fin", "equalizerDisable": "Desactivar ecualizador", "helpTitle": "Ayuda y tutorial", - "helpSubtitle": "Repasá funciones, consejos y novedades de PluriWave.", + "helpSubtitle": "9 pantallas · vuelve a verlo cuando quieras", + "tutorialSkipAction": "Saltar", + "tutorialNextAction": "Siguiente", + "tutorialPage1Headline": "Guarda tus emisoras y agrúpalas", + "tutorialPage1Body": "Toca el corazón para guardar una emisora. En «Tus emisoras» puedes crear grupos como «Cada mañana» o «Coche» y reordenarlas arrastrando.", + "tutorialPage2Headline": "Un ecualizador base y otro por emisora", + "tutorialPage2Body": "En Ajustes defines el ecualizador general. Y desde la reproducción de una emisora concreta puedes darle su propio ajuste, que manda sobre el general.", + "tutorialPage3Headline": "Graba lo que estás escuchando", + "tutorialPage3Body": "Desde la bandeja de herramientas del reproductor, «Grabar» guarda el stream original. Encuentra tus grabaciones en Ajustes › Grabaciones.", + "tutorialPage4Headline": "Alarmas que se adaptan a ti", + "tutorialPage4Body": "Despiértate con tu emisora favorita, pospón 3, 5 o 10 minutos, y añade rangos de vacaciones para que algunas alarmas se salten solas.", + "tutorialPage5Headline": "Tus favoritas, también en el coche", + "tutorialPage5Body": "Conecta el móvil con Android Auto y encontrarás Favoritos, Todas las emisoras, Mis emisoras y tu Música Local, con botones grandes pensados para conducir.", + "tutorialPage6Headline": "Se reconecta sola", + "tutorialPage6Body": "Si se corta la señal, PluriWave reintenta automáticamente y sigue mostrando tus favoritas guardadas aunque no tengas conexión.", + "tutorialPage7Headline": "Elige cuánto posponer", + "tutorialPage7Body": "Cuando suene una alarma, no hay un único «posponer»: eliges 3, 5 o 10 minutos según lo que necesites en ese momento.", + "tutorialPage8Headline": "¿No la encuentras? Añádela tú", + "tutorialPage8Body": "En «Tus emisoras» → Añadir emisora personalizada pega la URL del stream de una emisora que no esté en el buscador. Se guarda en «Mis emisoras», también disponible en el coche.", + "tutorialPage9Headline": "Listo, ya conoces lo esencial", + "tutorialPage9BannerBody": "Para volver a ver este tutorial cuando quieras: Ajustes → Información → Ayuda y tutorial.", "indefiniteOption": "Indefinida", "invalidNumber": "Número inválido", "nameLabel": "Nombre", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index e1abd72..9ab6328 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -604,7 +604,27 @@ "endLabel": "Fin", "equalizerDisable": "Désactiver l’égaliseur", "helpTitle": "Aide et tutoriel", - "helpSubtitle": "Revoyez les fonctions, conseils et nouveautés de PluriWave.", + "helpSubtitle": "9 écrans · à revoir quand vous voulez", + "tutorialSkipAction": "Passer", + "tutorialNextAction": "Suivant", + "tutorialPage1Headline": "Enregistrez vos stations et regroupez-les", + "tutorialPage1Body": "Touchez le cœur pour enregistrer une station. Dans « Vos stations », vous pouvez créer des groupes comme « Chaque matin » ou « Voiture » et les réorganiser en les faisant glisser.", + "tutorialPage2Headline": "Un égaliseur général et un autre par station", + "tutorialPage2Body": "Dans Réglages, vous définissez l'égaliseur général. Et depuis la lecture d'une station précise, vous pouvez lui donner son propre réglage, qui prévaut sur le général.", + "tutorialPage3Headline": "Enregistrez ce que vous écoutez", + "tutorialPage3Body": "Depuis la barre d'outils du lecteur, « Enregistrer » sauvegarde le flux original. Retrouvez vos enregistrements dans Réglages › Enregistrements.", + "tutorialPage4Headline": "Des alarmes qui s'adaptent à vous", + "tutorialPage4Body": "Réveillez-vous avec votre station préférée, reportez de 3, 5 ou 10 minutes, et ajoutez des périodes de vacances pour que certaines alarmes se sautent d'elles-mêmes.", + "tutorialPage5Headline": "Vos favoris, aussi en voiture", + "tutorialPage5Body": "Connectez votre téléphone avec Android Auto et retrouvez Favoris, Toutes les stations, Vos stations et votre Musique locale, avec de grands boutons pensés pour la conduite.", + "tutorialPage6Headline": "Se reconnecte toute seule", + "tutorialPage6Body": "Si le signal se coupe, PluriWave retente automatiquement et continue d'afficher vos favoris enregistrés même sans connexion.", + "tutorialPage7Headline": "Choisissez combien de temps reporter", + "tutorialPage7Body": "Quand une alarme sonne, il n'y a pas un seul « reporter » : vous choisissez 3, 5 ou 10 minutes selon ce dont vous avez besoin à ce moment-là.", + "tutorialPage8Headline": "Vous ne la trouvez pas ? Ajoutez-la vous-même", + "tutorialPage8Body": "Dans « Vos stations » → Ajouter une station personnalisée, collez l'URL du flux d'une station absente des résultats de recherche. Elle est enregistrée dans « Vos stations », aussi disponible en voiture.", + "tutorialPage9Headline": "Voilà, vous connaissez l'essentiel", + "tutorialPage9BannerBody": "Pour revoir ce tutoriel quand vous le souhaitez : Réglages → Informations → Aide et tutoriel.", "indefiniteOption": "Indéfinie", "invalidNumber": "Nombre invalide", "nameLabel": "Nom", diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index 3addd01..13cac7d 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -604,7 +604,27 @@ "endLabel": "समाप्ति", "equalizerDisable": "इक्वलाइज़र बंद करें", "helpTitle": "मदद और ट्यूटोरियल", - "helpSubtitle": "PluriWave की सुविधाएँ, सुझाव और नया क्या है देखें।", + "helpSubtitle": "9 स्क्रीन · जब चाहें दोबारा देखें", + "tutorialSkipAction": "छोड़ें", + "tutorialNextAction": "अगला", + "tutorialPage1Headline": "अपने स्टेशन सहेजें और उन्हें समूहों में बाँटें", + "tutorialPage1Body": "किसी स्टेशन को सहेजने के लिए दिल के आइकॉन पर टैप करें। «आपके स्टेशन» में आप «हर सुबह» या «कार» जैसे समूह बना सकते हैं और उन्हें खींचकर पुनः क्रमबद्ध कर सकते हैं।", + "tutorialPage2Headline": "एक सामान्य इक्वलाइज़र, और हर स्टेशन के लिए एक अलग", + "tutorialPage2Body": "सेटिंग्स में आप सामान्य इक्वलाइज़र सेट करते हैं। और किसी खास स्टेशन को चलाते समय आप उसे अपनी खुद की सेटिंग दे सकते हैं, जो सामान्य सेटिंग पर प्राथमिकता रखती है।", + "tutorialPage3Headline": "जो सुन रहे हैं उसे रिकॉर्ड करें", + "tutorialPage3Body": "प्लेयर की टूल ट्रे से, «रिकॉर्ड करें» मूल स्ट्रीम को सहेजता है। अपनी रिकॉर्डिंग सेटिंग्स › रिकॉर्डिंग में पाएँ।", + "tutorialPage4Headline": "अलार्म जो आपके अनुसार ढलते हैं", + "tutorialPage4Body": "अपने पसंदीदा स्टेशन के साथ जागें, 3, 5 या 10 मिनट के लिए स्नूज़ करें, और छुट्टियों की अवधि जोड़ें ताकि कुछ अलार्म खुद-ब-खुद छूट जाएँ।", + "tutorialPage5Headline": "आपके पसंदीदा, कार में भी", + "tutorialPage5Body": "अपने फ़ोन को Android Auto से जोड़ें और पाएँ पसंदीदा, सभी स्टेशन, आपके स्टेशन और आपका लोकल म्यूज़िक, ड्राइविंग के लिए बने बड़े बटनों के साथ।", + "tutorialPage6Headline": "खुद ही फिर से जुड़ जाता है", + "tutorialPage6Body": "अगर सिग्नल कट जाए, तो PluriWave अपने आप फिर कोशिश करता है और बिना कनेक्शन के भी आपके सहेजे गए पसंदीदा दिखाता रहता है।", + "tutorialPage7Headline": "चुनें कितनी देर के लिए स्नूज़ करना है", + "tutorialPage7Body": "जब कोई अलार्म बजता है, तो «स्नूज़» का कोई एक ही विकल्प नहीं होता: आप उस पल की ज़रूरत के अनुसार 3, 5 या 10 मिनट चुनते हैं।", + "tutorialPage8Headline": "नहीं मिल रहा? खुद जोड़ें", + "tutorialPage8Body": "«आपके स्टेशन» → कस्टम स्टेशन जोड़ें में, खोज में न मिलने वाले स्टेशन का स्ट्रीम URL पेस्ट करें। यह «आपके स्टेशन» में सहेजा जाता है और कार में भी उपलब्ध रहता है।", + "tutorialPage9Headline": "हो गया, अब आप ज़रूरी बातें जानते हैं", + "tutorialPage9BannerBody": "इस ट्यूटोरियल को दोबारा देखने के लिए: सेटिंग्स → जानकारी → मदद और ट्यूटोरियल।", "indefiniteOption": "अनिश्चित", "invalidNumber": "अमान्य संख्या", "nameLabel": "नाम", diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 7af1ab3..4864f62 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -604,7 +604,27 @@ "endLabel": "Selesai", "equalizerDisable": "Nonaktifkan equalizer", "helpTitle": "Bantuan dan tutorial", - "helpSubtitle": "Tinjau fitur, tips, dan hal baru di PluriWave.", + "helpSubtitle": "9 layar · lihat lagi kapan saja", + "tutorialSkipAction": "Lewati", + "tutorialNextAction": "Berikutnya", + "tutorialPage1Headline": "Simpan stasiun Anda dan kelompokkan", + "tutorialPage1Body": "Ketuk ikon hati untuk menyimpan stasiun. Di «Stasiun Anda» Anda bisa membuat grup seperti «Setiap pagi» atau «Mobil» dan mengurutkannya ulang dengan menyeret.", + "tutorialPage2Headline": "Satu equalizer umum, dan satu lagi per stasiun", + "tutorialPage2Body": "Di Pengaturan, Anda menentukan equalizer umum. Dan dari pemutaran stasiun tertentu, Anda bisa memberinya pengaturan sendiri, yang lebih diutamakan daripada pengaturan umum.", + "tutorialPage3Headline": "Rekam apa yang sedang Anda dengarkan", + "tutorialPage3Body": "Dari baki alat pemutar, «Rekam» menyimpan stream asli. Temukan rekaman Anda di Pengaturan › Rekaman.", + "tutorialPage4Headline": "Alarm yang menyesuaikan diri dengan Anda", + "tutorialPage4Body": "Bangun dengan stasiun favorit Anda, tunda 3, 5, atau 10 menit, dan tambahkan rentang liburan agar sebagian alarm melewati dirinya sendiri.", + "tutorialPage5Headline": "Favorit Anda, juga di mobil", + "tutorialPage5Body": "Sambungkan ponsel Anda dengan Android Auto dan temukan Favorit, Semua stasiun, Stasiun Anda, dan Musik Lokal Anda, dengan tombol besar yang dirancang untuk berkendara.", + "tutorialPage6Headline": "Tersambung ulang dengan sendirinya", + "tutorialPage6Body": "Jika sinyal terputus, PluriWave mencoba lagi secara otomatis dan tetap menampilkan favorit tersimpan Anda meski tanpa koneksi.", + "tutorialPage7Headline": "Pilih berapa lama menunda", + "tutorialPage7Body": "Saat alarm berbunyi, tidak ada satu «tunda» saja: Anda memilih 3, 5, atau 10 menit sesuai yang Anda butuhkan saat itu.", + "tutorialPage8Headline": "Tidak menemukannya? Tambahkan sendiri", + "tutorialPage8Body": "Di «Stasiun Anda» → Tambah stasiun khusus, tempel URL stream stasiun yang tidak ada di hasil pencarian. Stasiun ini disimpan di «Stasiun Anda», juga tersedia di mobil.", + "tutorialPage9Headline": "Selesai, Anda sudah tahu yang penting", + "tutorialPage9BannerBody": "Untuk melihat tutorial ini lagi kapan saja: Pengaturan → Informasi → Bantuan dan tutorial.", "indefiniteOption": "Tidak terbatas", "invalidNumber": "Nomor tidak valid", "nameLabel": "Nama", diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 5677f83..31e6a46 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -604,7 +604,27 @@ "endLabel": "Fine", "equalizerDisable": "Disattiva equalizzatore", "helpTitle": "Aiuto e tutorial", - "helpSubtitle": "Rivedi funzioni, consigli e novità di PluriWave.", + "helpSubtitle": "9 schermate · rivedilo quando vuoi", + "tutorialSkipAction": "Salta", + "tutorialNextAction": "Avanti", + "tutorialPage1Headline": "Salva le tue emittenti e raggruppale", + "tutorialPage1Body": "Tocca il cuore per salvare un'emittente. In «Le tue emittenti» puoi creare gruppi come «Ogni mattina» o «Auto» e riordinarle trascinandole.", + "tutorialPage2Headline": "Un equalizzatore di base e uno per emittente", + "tutorialPage2Body": "Nelle Impostazioni definisci l'equalizzatore generale. E dalla riproduzione di un'emittente specifica puoi darle un'impostazione propria, che ha la priorità su quella generale.", + "tutorialPage3Headline": "Registra ciò che stai ascoltando", + "tutorialPage3Body": "Dal vassoio degli strumenti del player, «Registra» salva lo stream originale. Trova le tue registrazioni in Impostazioni › Registrazioni.", + "tutorialPage4Headline": "Sveglie che si adattano a te", + "tutorialPage4Body": "Svegliati con la tua emittente preferita, posticipa di 3, 5 o 10 minuti, e aggiungi intervalli di vacanza in modo che alcune sveglie si saltino da sole.", + "tutorialPage5Headline": "I tuoi preferiti, anche in auto", + "tutorialPage5Body": "Collega il telefono con Android Auto e troverai Preferiti, Tutte le emittenti, Le tue emittenti e la tua Musica locale, con pulsanti grandi pensati per la guida.", + "tutorialPage6Headline": "Si riconnette da sola", + "tutorialPage6Body": "Se il segnale cade, PluriWave riprova automaticamente e continua a mostrare i tuoi preferiti salvati anche senza connessione.", + "tutorialPage7Headline": "Scegli quanto posticipare", + "tutorialPage7Body": "Quando suona una sveglia, non c'è un solo «posticipa»: scegli 3, 5 o 10 minuti a seconda di cosa ti serve in quel momento.", + "tutorialPage8Headline": "Non la trovi? Aggiungila tu", + "tutorialPage8Body": "In «Le tue emittenti» → Aggiungi emittente personalizzata incolla l'URL dello stream di un'emittente non presente nella ricerca. Viene salvata in «Le tue emittenti», disponibile anche in auto.", + "tutorialPage9Headline": "Fatto, ora conosci l'essenziale", + "tutorialPage9BannerBody": "Per rivedere questo tutorial quando vuoi: Impostazioni → Informazioni → Aiuto e tutorial.", "indefiniteOption": "Indefinita", "invalidNumber": "Numero non valido", "nameLabel": "Nome", diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index 444554b..1327254 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -604,7 +604,27 @@ "endLabel": "終了", "equalizerDisable": "イコライザーを無効化", "helpTitle": "ヘルプとチュートリアル", - "helpSubtitle": "PluriWaveの機能、ヒント、新着情報を確認できます。", + "helpSubtitle": "全9画面・いつでも見返せます", + "tutorialSkipAction": "スキップ", + "tutorialNextAction": "次へ", + "tutorialPage1Headline": "お気に入りの局を保存してグループ分け", + "tutorialPage1Body": "ハートをタップして局を保存しましょう。「あなたの局」では「毎朝」や「車」などのグループを作り、ドラッグして並べ替えられます。", + "tutorialPage2Headline": "基本のイコライザーと局ごとのイコライザー", + "tutorialPage2Body": "設定で全体のイコライザーを決められます。特定の局を再生中は、その局専用の設定を適用でき、全体設定より優先されます。", + "tutorialPage3Headline": "聴いている番組を録音", + "tutorialPage3Body": "プレーヤーのツールトレイから「録音」をタップすると、元のストリームが保存されます。録音は設定›録音で確認できます。", + "tutorialPage4Headline": "あなたに合わせてくれるアラーム", + "tutorialPage4Body": "お気に入りの局で目覚め、3分・5分・10分でスヌーズでき、休暇期間を追加すれば一部のアラームを自動でスキップできます。", + "tutorialPage5Headline": "お気に入りは車でも", + "tutorialPage5Body": "スマートフォンをAndroid Autoに接続すると、お気に入り、すべての局、あなたの局、ローカルミュージックが、運転向けの大きなボタンで使えます。", + "tutorialPage6Headline": "自動で再接続", + "tutorialPage6Body": "電波が途切れても、PluriWaveは自動的に再試行し、接続がなくても保存済みのお気に入りを表示し続けます。", + "tutorialPage7Headline": "スヌーズ時間を選べる", + "tutorialPage7Body": "アラームが鳴ったとき、「スヌーズ」は一つだけではありません。3分・5分・10分から、その時必要な時間を選べます。", + "tutorialPage8Headline": "見つからない?自分で追加", + "tutorialPage8Body": "「あなたの局」→カスタム局を追加で、検索にない局のストリームURLを貼り付けられます。「あなたの局」に保存され、車でも利用できます。", + "tutorialPage9Headline": "完了、基本はこれで押さえました", + "tutorialPage9BannerBody": "このチュートリアルはいつでも再確認できます:設定 → 情報 → ヘルプとチュートリアル。", "indefiniteOption": "無期限", "invalidNumber": "無効な数値", "nameLabel": "名前", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 2b41a67..1702dd3 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -604,7 +604,27 @@ "endLabel": "Fim", "equalizerDisable": "Desativar equalizador", "helpTitle": "Ajuda e tutorial", - "helpSubtitle": "Revê funções, dicas e novidades do PluriWave.", + "helpSubtitle": "9 ecrãs · reveja quando quiser", + "tutorialSkipAction": "Pular", + "tutorialNextAction": "Avançar", + "tutorialPage1Headline": "Guarde as suas estações e agrupe-as", + "tutorialPage1Body": "Toque no coração para guardar uma estação. Em «Suas estações» pode criar grupos como «Todas as manhãs» ou «Carro» e reordená-las arrastando.", + "tutorialPage2Headline": "Um equalizador geral e outro por estação", + "tutorialPage2Body": "Em Definições define o equalizador geral. E, ao reproduzir uma estação específica, pode dar-lhe o seu próprio ajuste, que prevalece sobre o geral.", + "tutorialPage3Headline": "Grave o que está a ouvir", + "tutorialPage3Body": "Na bandeja de ferramentas do leitor, «Gravar» guarda o stream original. Encontre as suas gravações em Definições › Gravações.", + "tutorialPage4Headline": "Alarmes que se adaptam a si", + "tutorialPage4Body": "Acorde com a sua estação favorita, adie 3, 5 ou 10 minutos, e adicione períodos de férias para que alguns alarmes se saltem sozinhos.", + "tutorialPage5Headline": "Os seus favoritos, também no carro", + "tutorialPage5Body": "Ligue o telemóvel ao Android Auto e encontre Favoritos, Todas as estações, Suas estações e a sua Música local, com botões grandes pensados para conduzir.", + "tutorialPage6Headline": "Reconecta-se sozinho", + "tutorialPage6Body": "Se o sinal cair, o PluriWave tenta novamente de forma automática e continua a mostrar os seus favoritos guardados mesmo sem ligação.", + "tutorialPage7Headline": "Escolha quanto tempo adiar", + "tutorialPage7Body": "Quando um alarme toca, não existe um único «adiar»: escolhe 3, 5 ou 10 minutos conforme o que precisar nesse momento.", + "tutorialPage8Headline": "Não a encontra? Adicione-a você mesmo", + "tutorialPage8Body": "Em «Suas estações» → Adicionar estação personalizada, cole o URL do stream de uma estação que não esteja na pesquisa. Fica guardada em «Suas estações», também disponível no carro.", + "tutorialPage9Headline": "Pronto, já conhece o essencial", + "tutorialPage9BannerBody": "Para rever este tutorial quando quiser: Definições → Informação → Ajuda e tutorial.", "indefiniteOption": "Indefinida", "invalidNumber": "Número inválido", "nameLabel": "Nome", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index c370a09..6b14723 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -604,7 +604,27 @@ "endLabel": "Конец", "equalizerDisable": "Отключить эквалайзер", "helpTitle": "Помощь и руководство", - "helpSubtitle": "Посмотрите функции, советы и новости PluriWave.", + "helpSubtitle": "9 экранов · смотрите снова в любое время", + "tutorialSkipAction": "Пропустить", + "tutorialNextAction": "Далее", + "tutorialPage1Headline": "Сохраняйте станции и группируйте их", + "tutorialPage1Body": "Нажмите на сердечко, чтобы сохранить станцию. В разделе «Ваши станции» можно создавать группы, например «Каждое утро» или «Машина», и менять порядок перетаскиванием.", + "tutorialPage2Headline": "Общий эквалайзер и отдельный для каждой станции", + "tutorialPage2Body": "В настройках вы задаёте общий эквалайзер. А во время воспроизведения конкретной станции можно задать для неё собственную настройку — она будет иметь приоритет над общей.", + "tutorialPage3Headline": "Записывайте то, что слушаете", + "tutorialPage3Body": "На панели инструментов плеера кнопка «Запись» сохраняет исходный поток. Ваши записи хранятся в разделе Настройки › Записи.", + "tutorialPage4Headline": "Будильники, которые подстраиваются под вас", + "tutorialPage4Body": "Просыпайтесь под любимую станцию, откладывайте на 3, 5 или 10 минут и добавляйте периоды отпуска, чтобы некоторые будильники пропускались сами.", + "tutorialPage5Headline": "Ваши избранные станции — и в машине тоже", + "tutorialPage5Body": "Подключите телефон через Android Auto, и вы найдёте Избранное, Все станции, Ваши станции и вашу локальную музыку с крупными кнопками, удобными за рулём.", + "tutorialPage6Headline": "Переподключается сам", + "tutorialPage6Body": "Если сигнал пропадает, PluriWave автоматически повторяет попытку и продолжает показывать сохранённые избранные станции даже без подключения.", + "tutorialPage7Headline": "Выбирайте, на сколько отложить", + "tutorialPage7Body": "Когда звонит будильник, нет единственного варианта «отложить»: выбирайте 3, 5 или 10 минут — в зависимости от того, что нужно именно сейчас.", + "tutorialPage8Headline": "Не нашли станцию? Добавьте её сами", + "tutorialPage8Body": "В разделе «Ваши станции» → Добавить свою станцию вставьте URL потока станции, которой нет в поиске. Она сохранится в «Ваши станции» и будет доступна и в машине.", + "tutorialPage9Headline": "Готово, теперь вы знаете самое важное", + "tutorialPage9BannerBody": "Чтобы посмотреть этот урок ещё раз: Настройки → Информация → Помощь и руководство.", "indefiniteOption": "Без ограничения", "invalidNumber": "Недопустимое число", "nameLabel": "Название", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index f27a9cc..484aad8 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -604,7 +604,27 @@ "endLabel": "结束", "equalizerDisable": "关闭均衡器", "helpTitle": "帮助和教程", - "helpSubtitle": "查看 PluriWave 的功能、技巧和新内容。", + "helpSubtitle": "共9屏 · 随时可重新查看", + "tutorialSkipAction": "跳过", + "tutorialNextAction": "下一步", + "tutorialPage1Headline": "保存并整理你的电台", + "tutorialPage1Body": "点击心形图标即可保存电台。在“你的电台”中,你可以创建“每天早上”或“车载”等分组,并通过拖动重新排序。", + "tutorialPage2Headline": "一个通用均衡器,外加每个电台专属的均衡器", + "tutorialPage2Body": "在设置中可以调整通用均衡器。播放某个电台时,你还可以为它单独设置均衡器,该设置优先于通用设置。", + "tutorialPage3Headline": "录制正在收听的内容", + "tutorialPage3Body": "在播放器工具栏中点击“录制”,即可保存原始音频流。录音内容可在 设置 › 录音 中查看。", + "tutorialPage4Headline": "会迁就你的闹钟", + "tutorialPage4Body": "用喜欢的电台唤醒自己,可以推迟3分钟、5分钟或10分钟,还能添加假期时间段,让部分闹钟自动跳过。", + "tutorialPage5Headline": "收藏的电台,车载也能用", + "tutorialPage5Body": "将手机连接到Android Auto,即可看到收藏、全部电台、你的电台和本地音乐,大按钮专为驾驶设计。", + "tutorialPage6Headline": "自动重新连接", + "tutorialPage6Body": "信号中断时,PluriWave会自动重试连接,即使暂时没有网络也会继续显示已保存的收藏电台。", + "tutorialPage7Headline": "自选推迟时长", + "tutorialPage7Body": "闹钟响起时,“推迟”并非只有一种选择:你可以根据当下需要选择推迟3分钟、5分钟或10分钟。", + "tutorialPage8Headline": "找不到?自己添加", + "tutorialPage8Body": "在“你的电台”→添加自定义电台中,粘贴搜索结果里没有的电台的流媒体URL即可。它会保存在“你的电台”中,车载模式下同样可用。", + "tutorialPage9Headline": "完成,你已经了解核心功能", + "tutorialPage9BannerBody": "想随时重新观看本教程:设置 → 信息 → 帮助与教程。", "indefiniteOption": "不限时", "invalidNumber": "数字无效", "nameLabel": "名称", diff --git a/lib/l10n/gen/app_localizations.dart b/lib/l10n/gen/app_localizations.dart index 81cac10..c6cb50f 100644 --- a/lib/l10n/gen/app_localizations.dart +++ b/lib/l10n/gen/app_localizations.dart @@ -2567,9 +2567,129 @@ abstract class AppLocalizations { /// No description provided for @helpSubtitle. /// /// In es, this message translates to: - /// **'Repasá funciones, consejos y novedades de PluriWave.'** + /// **'9 pantallas · vuelve a verlo cuando quieras'** String get helpSubtitle; + /// No description provided for @tutorialSkipAction. + /// + /// In es, this message translates to: + /// **'Saltar'** + String get tutorialSkipAction; + + /// No description provided for @tutorialNextAction. + /// + /// In es, this message translates to: + /// **'Siguiente'** + String get tutorialNextAction; + + /// No description provided for @tutorialPage1Headline. + /// + /// In es, this message translates to: + /// **'Guarda tus emisoras y agrúpalas'** + String get tutorialPage1Headline; + + /// No description provided for @tutorialPage1Body. + /// + /// In es, this message translates to: + /// **'Toca el corazón para guardar una emisora. En «Tus emisoras» puedes crear grupos como «Cada mañana» o «Coche» y reordenarlas arrastrando.'** + String get tutorialPage1Body; + + /// No description provided for @tutorialPage2Headline. + /// + /// In es, this message translates to: + /// **'Un ecualizador base y otro por emisora'** + String get tutorialPage2Headline; + + /// No description provided for @tutorialPage2Body. + /// + /// In es, this message translates to: + /// **'En Ajustes defines el ecualizador general. Y desde la reproducción de una emisora concreta puedes darle su propio ajuste, que manda sobre el general.'** + String get tutorialPage2Body; + + /// No description provided for @tutorialPage3Headline. + /// + /// In es, this message translates to: + /// **'Graba lo que estás escuchando'** + String get tutorialPage3Headline; + + /// No description provided for @tutorialPage3Body. + /// + /// In es, this message translates to: + /// **'Desde la bandeja de herramientas del reproductor, «Grabar» guarda el stream original. Encuentra tus grabaciones en Ajustes › Grabaciones.'** + String get tutorialPage3Body; + + /// No description provided for @tutorialPage4Headline. + /// + /// In es, this message translates to: + /// **'Alarmas que se adaptan a ti'** + String get tutorialPage4Headline; + + /// No description provided for @tutorialPage4Body. + /// + /// In es, this message translates to: + /// **'Despiértate con tu emisora favorita, pospón 3, 5 o 10 minutos, y añade rangos de vacaciones para que algunas alarmas se salten solas.'** + String get tutorialPage4Body; + + /// No description provided for @tutorialPage5Headline. + /// + /// In es, this message translates to: + /// **'Tus favoritas, también en el coche'** + String get tutorialPage5Headline; + + /// No description provided for @tutorialPage5Body. + /// + /// In es, this message translates to: + /// **'Conecta el móvil con Android Auto y encontrarás Favoritos, Todas las emisoras, Mis emisoras y tu Música Local, con botones grandes pensados para conducir.'** + String get tutorialPage5Body; + + /// No description provided for @tutorialPage6Headline. + /// + /// In es, this message translates to: + /// **'Se reconecta sola'** + String get tutorialPage6Headline; + + /// No description provided for @tutorialPage6Body. + /// + /// In es, this message translates to: + /// **'Si se corta la señal, PluriWave reintenta automáticamente y sigue mostrando tus favoritas guardadas aunque no tengas conexión.'** + String get tutorialPage6Body; + + /// No description provided for @tutorialPage7Headline. + /// + /// In es, this message translates to: + /// **'Elige cuánto posponer'** + String get tutorialPage7Headline; + + /// No description provided for @tutorialPage7Body. + /// + /// In es, this message translates to: + /// **'Cuando suene una alarma, no hay un único «posponer»: eliges 3, 5 o 10 minutos según lo que necesites en ese momento.'** + String get tutorialPage7Body; + + /// No description provided for @tutorialPage8Headline. + /// + /// In es, this message translates to: + /// **'¿No la encuentras? Añádela tú'** + String get tutorialPage8Headline; + + /// No description provided for @tutorialPage8Body. + /// + /// In es, this message translates to: + /// **'En «Tus emisoras» → Añadir emisora personalizada pega la URL del stream de una emisora que no esté en el buscador. Se guarda en «Mis emisoras», también disponible en el coche.'** + String get tutorialPage8Body; + + /// No description provided for @tutorialPage9Headline. + /// + /// In es, this message translates to: + /// **'Listo, ya conoces lo esencial'** + String get tutorialPage9Headline; + + /// No description provided for @tutorialPage9BannerBody. + /// + /// In es, this message translates to: + /// **'Para volver a ver este tutorial cuando quieras: Ajustes → Información → Ayuda y tutorial.'** + String get tutorialPage9BannerBody; + /// No description provided for @indefiniteOption. /// /// In es, this message translates to: diff --git a/lib/l10n/gen/app_localizations_ar.dart b/lib/l10n/gen/app_localizations_ar.dart index 5726266..db5e4a4 100644 --- a/lib/l10n/gen/app_localizations_ar.dart +++ b/lib/l10n/gen/app_localizations_ar.dart @@ -1407,7 +1407,76 @@ class AppLocalizationsAr extends AppLocalizations { String get helpTitle => 'المساعدة والشرح'; @override - String get helpSubtitle => 'راجع ميزات PluriWave والنصائح والمستجدات.'; + String get helpSubtitle => '9 شاشات · شاهده مجددًا متى شئت'; + + @override + String get tutorialSkipAction => 'تخطي'; + + @override + String get tutorialNextAction => 'التالي'; + + @override + String get tutorialPage1Headline => 'احفظ محطاتك ونظّمها في مجموعات'; + + @override + String get tutorialPage1Body => + 'اضغط على أيقونة القلب لحفظ محطة. في «محطاتك» يمكنك إنشاء مجموعات مثل «كل صباح» أو «السيارة» وإعادة ترتيبها بالسحب.'; + + @override + String get tutorialPage2Headline => 'معادل صوت عام وآخر لكل محطة'; + + @override + String get tutorialPage2Body => + 'من الإعدادات تحدد المعادل الصوتي العام. ومن تشغيل محطة معينة يمكنك ضبط إعداد خاص بها، له الأولوية على الإعداد العام.'; + + @override + String get tutorialPage3Headline => 'سجّل ما تستمع إليه'; + + @override + String get tutorialPage3Body => + 'من شريط أدوات المشغل، يحفظ زر «تسجيل» البث الأصلي. ستجد تسجيلاتك في الإعدادات › التسجيلات.'; + + @override + String get tutorialPage4Headline => 'منبهات تتكيّف معك'; + + @override + String get tutorialPage4Body => + 'استيقظ على محطتك المفضلة، وأجّل المنبه 3 أو 5 أو 10 دقائق، وأضف فترات إجازة ليتخطى بعض المنبهات نفسه تلقائيًا.'; + + @override + String get tutorialPage5Headline => 'محطاتك المفضلة، في السيارة أيضًا'; + + @override + String get tutorialPage5Body => + 'اربط هاتفك بـ Android Auto لتجد المفضلة وجميع المحطات ومحطاتك والموسيقى المحلية، بأزرار كبيرة مصممة للقيادة.'; + + @override + String get tutorialPage6Headline => 'يعيد الاتصال تلقائيًا'; + + @override + String get tutorialPage6Body => + 'إذا انقطعت الإشارة، تعيد PluriWave المحاولة تلقائيًا وتستمر في عرض محطاتك المفضلة المحفوظة حتى بدون اتصال.'; + + @override + String get tutorialPage7Headline => 'اختر مدة التأجيل'; + + @override + String get tutorialPage7Body => + 'عند رنين المنبه، لا يوجد خيار تأجيل واحد فقط: تختار 3 أو 5 أو 10 دقائق حسب ما تحتاجه في تلك اللحظة.'; + + @override + String get tutorialPage8Headline => 'لم تجدها؟ أضفها بنفسك'; + + @override + String get tutorialPage8Body => + 'من «محطاتك» ← إضافة محطة مخصصة، الصق رابط بث محطة غير موجودة في نتائج البحث. تُحفظ في «محطاتك»، وتكون متاحة في السيارة أيضًا.'; + + @override + String get tutorialPage9Headline => 'تمّ، أصبحت تعرف الأساسيات'; + + @override + String get tutorialPage9BannerBody => + 'لمشاهدة هذا الشرح مرة أخرى في أي وقت: الإعدادات ← المعلومات ← المساعدة والشرح.'; @override String get indefiniteOption => 'غير محدد'; diff --git a/lib/l10n/gen/app_localizations_bn.dart b/lib/l10n/gen/app_localizations_bn.dart index c7939b9..5bb11da 100644 --- a/lib/l10n/gen/app_localizations_bn.dart +++ b/lib/l10n/gen/app_localizations_bn.dart @@ -1417,7 +1417,79 @@ class AppLocalizationsBn extends AppLocalizations { String get helpTitle => 'সহায়তা ও টিউটোরিয়াল'; @override - String get helpSubtitle => 'PluriWave-এর ফিচার, টিপস ও নতুন বিষয়গুলো দেখুন।'; + String get helpSubtitle => '৯টি স্ক্রিন · যখন খুশি আবার দেখুন'; + + @override + String get tutorialSkipAction => 'এড়িয়ে যান'; + + @override + String get tutorialNextAction => 'পরবর্তী'; + + @override + String get tutorialPage1Headline => + 'আপনার স্টেশন সংরক্ষণ করুন এবং গ্রুপে ভাগ করুন'; + + @override + String get tutorialPage1Body => + 'একটি স্টেশন সংরক্ষণ করতে হার্ট আইকনে ট্যাপ করুন। «আপনার স্টেশন»-এ আপনি «প্রতিদিন সকালে» বা «গাড়ি»-এর মতো গ্রুপ তৈরি করতে পারেন এবং টেনে সেগুলোর ক্রম বদলাতে পারেন।'; + + @override + String get tutorialPage2Headline => + 'একটি সাধারণ ইকুয়ালাইজার, প্রতিটি স্টেশনের জন্য আরেকটি'; + + @override + String get tutorialPage2Body => + 'সেটিংসে আপনি সাধারণ ইকুয়ালাইজার ঠিক করেন। আর কোনো নির্দিষ্ট স্টেশন চালানোর সময় আপনি সেটির নিজস্ব সেটিং দিতে পারেন, যা সাধারণ সেটিংয়ের চেয়ে অগ্রাধিকার পায়।'; + + @override + String get tutorialPage3Headline => 'যা শুনছেন তা রেকর্ড করুন'; + + @override + String get tutorialPage3Body => + 'প্লেয়ারের টুল ট্রে থেকে «রেকর্ড করুন» মূল স্ট্রিম সংরক্ষণ করে। আপনার রেকর্ডিং পাবেন সেটিংস › রেকর্ডিং-এ।'; + + @override + String get tutorialPage4Headline => + 'এমন অ্যালার্ম যা আপনার সাথে মানিয়ে নেয়'; + + @override + String get tutorialPage4Body => + 'আপনার প্রিয় স্টেশনে জেগে উঠুন, ৩, ৫ বা ১০ মিনিট স্নুজ করুন, এবং ছুটির সময়সীমা যোগ করুন যাতে কিছু অ্যালার্ম নিজে থেকেই বাদ পড়ে।'; + + @override + String get tutorialPage5Headline => 'আপনার প্রিয়গুলো, গাড়িতেও'; + + @override + String get tutorialPage5Body => + 'আপনার ফোন Android Auto-এর সাথে সংযুক্ত করুন এবং পাবেন প্রিয়, সব স্টেশন, আপনার স্টেশন এবং আপনার লোকাল মিউজিক, গাড়ি চালানোর উপযোগী বড় বোতামসহ।'; + + @override + String get tutorialPage6Headline => 'নিজে থেকেই আবার সংযুক্ত হয়'; + + @override + String get tutorialPage6Body => + 'সিগন্যাল কেটে গেলে, PluriWave স্বয়ংক্রিয়ভাবে আবার চেষ্টা করে এবং সংযোগ ছাড়াই আপনার সংরক্ষিত প্রিয়গুলো দেখাতে থাকে।'; + + @override + String get tutorialPage7Headline => 'কতক্ষণ স্নুজ করবেন তা বেছে নিন'; + + @override + String get tutorialPage7Body => + 'অ্যালার্ম বাজলে, «স্নুজ»-এর একটিমাত্র বিকল্প নেই: আপনি সেই মুহূর্তে প্রয়োজন অনুযায়ী ৩, ৫ বা ১০ মিনিট বেছে নেন।'; + + @override + String get tutorialPage8Headline => 'খুঁজে পাচ্ছেন না? নিজেই যোগ করুন'; + + @override + String get tutorialPage8Body => + '«আপনার স্টেশন» → কাস্টম স্টেশন যোগ করুন-এ, খোঁজে না পাওয়া স্টেশনের স্ট্রিম URL পেস্ট করুন। এটি «আপনার স্টেশন»-এ সংরক্ষিত হয় এবং গাড়িতেও পাওয়া যায়।'; + + @override + String get tutorialPage9Headline => 'শেষ, এখন আপনি মূল বিষয়গুলো জানেন'; + + @override + String get tutorialPage9BannerBody => + 'এই টিউটোরিয়ালটি আবার দেখতে: সেটিংস → তথ্য → সহায়তা ও টিউটোরিয়াল।'; @override String get indefiniteOption => 'অনির্দিষ্ট'; diff --git a/lib/l10n/gen/app_localizations_de.dart b/lib/l10n/gen/app_localizations_de.dart index a6c33af..732a38f 100644 --- a/lib/l10n/gen/app_localizations_de.dart +++ b/lib/l10n/gen/app_localizations_de.dart @@ -1425,8 +1425,79 @@ class AppLocalizationsDe extends AppLocalizations { String get helpTitle => 'Hilfe und Tutorial'; @override - String get helpSubtitle => - 'Funktionen, Tipps und Neuigkeiten von PluriWave ansehen.'; + String get helpSubtitle => '9 Bildschirme · jederzeit erneut ansehen'; + + @override + String get tutorialSkipAction => 'Überspringen'; + + @override + String get tutorialNextAction => 'Weiter'; + + @override + String get tutorialPage1Headline => + 'Speichere deine Sender und gruppiere sie'; + + @override + String get tutorialPage1Body => + 'Tippe auf das Herz, um einen Sender zu speichern. Unter „Deine Sender“ kannst du Gruppen wie „Jeden Morgen“ oder „Auto“ anlegen und sie per Ziehen neu anordnen.'; + + @override + String get tutorialPage2Headline => + 'Ein Basis-Equalizer und einer pro Sender'; + + @override + String get tutorialPage2Body => + 'In den Einstellungen legst du den allgemeinen Equalizer fest. Und während der Wiedergabe eines bestimmten Senders kannst du ihm eine eigene Einstellung geben, die Vorrang vor der allgemeinen hat.'; + + @override + String get tutorialPage3Headline => 'Nimm auf, was du gerade hörst'; + + @override + String get tutorialPage3Body => + 'Über die Werkzeugleiste des Players speichert „Aufnehmen“ den Original-Stream. Deine Aufnahmen findest du unter Einstellungen › Aufnahmen.'; + + @override + String get tutorialPage4Headline => 'Alarme, die sich dir anpassen'; + + @override + String get tutorialPage4Body => + 'Wach mit deinem Lieblingssender auf, schlummere 3, 5 oder 10 Minuten weiter und füge Urlaubszeiträume hinzu, damit manche Alarme von selbst ausgesetzt werden.'; + + @override + String get tutorialPage5Headline => 'Deine Favoriten, auch im Auto'; + + @override + String get tutorialPage5Body => + 'Verbinde dein Handy mit Android Auto und finde Favoriten, Alle Sender, Deine Sender und deine lokale Musik, mit großen, fürs Fahren gemachten Tasten.'; + + @override + String get tutorialPage6Headline => 'Verbindet sich von selbst neu'; + + @override + String get tutorialPage6Body => + 'Bricht das Signal ab, versucht PluriWave automatisch erneut und zeigt weiterhin deine gespeicherten Favoriten, auch ohne Verbindung.'; + + @override + String get tutorialPage7Headline => 'Wähle, wie lange du schlummerst'; + + @override + String get tutorialPage7Body => + 'Wenn ein Alarm klingelt, gibt es nicht nur ein „Schlummern“: Du wählst 3, 5 oder 10 Minuten, je nachdem, was du gerade brauchst.'; + + @override + String get tutorialPage8Headline => + 'Findest du ihn nicht? Füge ihn selbst hinzu'; + + @override + String get tutorialPage8Body => + 'Füge unter „Deine Sender“ → Eigenen Sender hinzufügen die Stream-URL eines Senders ein, der nicht in der Suche auftaucht. Er wird unter „Deine Sender“ gespeichert und ist auch im Auto verfügbar.'; + + @override + String get tutorialPage9Headline => 'Fertig, du kennst jetzt das Wichtigste'; + + @override + String get tutorialPage9BannerBody => + 'Um dieses Tutorial jederzeit erneut anzusehen: Einstellungen → Info → Hilfe und Tutorial.'; @override String get indefiniteOption => 'Unbegrenzt'; diff --git a/lib/l10n/gen/app_localizations_en.dart b/lib/l10n/gen/app_localizations_en.dart index d73df11..0e416a1 100644 --- a/lib/l10n/gen/app_localizations_en.dart +++ b/lib/l10n/gen/app_localizations_en.dart @@ -1408,7 +1408,77 @@ class AppLocalizationsEn extends AppLocalizations { String get helpTitle => 'Help and tutorial'; @override - String get helpSubtitle => 'Review PluriWave features, tips and what’s new.'; + String get helpSubtitle => '9 screens · watch it again anytime'; + + @override + String get tutorialSkipAction => 'Skip'; + + @override + String get tutorialNextAction => 'Next'; + + @override + String get tutorialPage1Headline => 'Save your stations and group them'; + + @override + String get tutorialPage1Body => + 'Tap the heart to save a station. In \"Your stations\" you can create groups like \"Every morning\" or \"Car\" and drag to reorder them.'; + + @override + String get tutorialPage2Headline => + 'One base equalizer, plus one per station'; + + @override + String get tutorialPage2Body => + 'In Settings you set the general equalizer. And from a specific station\'s playback screen you can give it its own setting, which overrides the general one.'; + + @override + String get tutorialPage3Headline => 'Record what you\'re listening to'; + + @override + String get tutorialPage3Body => + 'From the player\'s tool tray, \"Record\" saves the original stream. Find your recordings under Settings › Recordings.'; + + @override + String get tutorialPage4Headline => 'Alarms that adapt to you'; + + @override + String get tutorialPage4Body => + 'Wake up to your favorite station, snooze for 3, 5, or 10 minutes, and add vacation ranges so some alarms skip themselves.'; + + @override + String get tutorialPage5Headline => 'Your favorites, in the car too'; + + @override + String get tutorialPage5Body => + 'Connect your phone with Android Auto to find Favorites, All stations, Your stations, and your Local Music, with big buttons made for driving.'; + + @override + String get tutorialPage6Headline => 'It reconnects on its own'; + + @override + String get tutorialPage6Body => + 'If the signal drops, PluriWave retries automatically and keeps showing your saved favorites even without a connection.'; + + @override + String get tutorialPage7Headline => 'Choose how long to snooze'; + + @override + String get tutorialPage7Body => + 'When an alarm rings, there\'s no single \"snooze\": you choose 3, 5, or 10 minutes depending on what you need at that moment.'; + + @override + String get tutorialPage8Headline => 'Can\'t find it? Add it yourself'; + + @override + String get tutorialPage8Body => + 'In \"Your stations\" → Add custom station, paste the stream URL of a station that isn\'t in the search results. It\'s saved under \"Your stations\", also available in the car.'; + + @override + String get tutorialPage9Headline => 'Done — now you know the essentials'; + + @override + String get tutorialPage9BannerBody => + 'To watch this tutorial again anytime: Settings → Information → Help and tutorial.'; @override String get indefiniteOption => 'Indefinite'; diff --git a/lib/l10n/gen/app_localizations_es.dart b/lib/l10n/gen/app_localizations_es.dart index cc6fc0d..2d6f10e 100644 --- a/lib/l10n/gen/app_localizations_es.dart +++ b/lib/l10n/gen/app_localizations_es.dart @@ -1419,8 +1419,76 @@ class AppLocalizationsEs extends AppLocalizations { String get helpTitle => 'Ayuda y tutorial'; @override - String get helpSubtitle => - 'Repasá funciones, consejos y novedades de PluriWave.'; + String get helpSubtitle => '9 pantallas · vuelve a verlo cuando quieras'; + + @override + String get tutorialSkipAction => 'Saltar'; + + @override + String get tutorialNextAction => 'Siguiente'; + + @override + String get tutorialPage1Headline => 'Guarda tus emisoras y agrúpalas'; + + @override + String get tutorialPage1Body => + 'Toca el corazón para guardar una emisora. En «Tus emisoras» puedes crear grupos como «Cada mañana» o «Coche» y reordenarlas arrastrando.'; + + @override + String get tutorialPage2Headline => 'Un ecualizador base y otro por emisora'; + + @override + String get tutorialPage2Body => + 'En Ajustes defines el ecualizador general. Y desde la reproducción de una emisora concreta puedes darle su propio ajuste, que manda sobre el general.'; + + @override + String get tutorialPage3Headline => 'Graba lo que estás escuchando'; + + @override + String get tutorialPage3Body => + 'Desde la bandeja de herramientas del reproductor, «Grabar» guarda el stream original. Encuentra tus grabaciones en Ajustes › Grabaciones.'; + + @override + String get tutorialPage4Headline => 'Alarmas que se adaptan a ti'; + + @override + String get tutorialPage4Body => + 'Despiértate con tu emisora favorita, pospón 3, 5 o 10 minutos, y añade rangos de vacaciones para que algunas alarmas se salten solas.'; + + @override + String get tutorialPage5Headline => 'Tus favoritas, también en el coche'; + + @override + String get tutorialPage5Body => + 'Conecta el móvil con Android Auto y encontrarás Favoritos, Todas las emisoras, Mis emisoras y tu Música Local, con botones grandes pensados para conducir.'; + + @override + String get tutorialPage6Headline => 'Se reconecta sola'; + + @override + String get tutorialPage6Body => + 'Si se corta la señal, PluriWave reintenta automáticamente y sigue mostrando tus favoritas guardadas aunque no tengas conexión.'; + + @override + String get tutorialPage7Headline => 'Elige cuánto posponer'; + + @override + String get tutorialPage7Body => + 'Cuando suene una alarma, no hay un único «posponer»: eliges 3, 5 o 10 minutos según lo que necesites en ese momento.'; + + @override + String get tutorialPage8Headline => '¿No la encuentras? Añádela tú'; + + @override + String get tutorialPage8Body => + 'En «Tus emisoras» → Añadir emisora personalizada pega la URL del stream de una emisora que no esté en el buscador. Se guarda en «Mis emisoras», también disponible en el coche.'; + + @override + String get tutorialPage9Headline => 'Listo, ya conoces lo esencial'; + + @override + String get tutorialPage9BannerBody => + 'Para volver a ver este tutorial cuando quieras: Ajustes → Información → Ayuda y tutorial.'; @override String get indefiniteOption => 'Indefinida'; diff --git a/lib/l10n/gen/app_localizations_fr.dart b/lib/l10n/gen/app_localizations_fr.dart index a0e0a48..4c4c487 100644 --- a/lib/l10n/gen/app_localizations_fr.dart +++ b/lib/l10n/gen/app_localizations_fr.dart @@ -1428,8 +1428,79 @@ class AppLocalizationsFr extends AppLocalizations { String get helpTitle => 'Aide et tutoriel'; @override - String get helpSubtitle => - 'Revoyez les fonctions, conseils et nouveautés de PluriWave.'; + String get helpSubtitle => '9 écrans · à revoir quand vous voulez'; + + @override + String get tutorialSkipAction => 'Passer'; + + @override + String get tutorialNextAction => 'Suivant'; + + @override + String get tutorialPage1Headline => + 'Enregistrez vos stations et regroupez-les'; + + @override + String get tutorialPage1Body => + 'Touchez le cœur pour enregistrer une station. Dans « Vos stations », vous pouvez créer des groupes comme « Chaque matin » ou « Voiture » et les réorganiser en les faisant glisser.'; + + @override + String get tutorialPage2Headline => + 'Un égaliseur général et un autre par station'; + + @override + String get tutorialPage2Body => + 'Dans Réglages, vous définissez l\'égaliseur général. Et depuis la lecture d\'une station précise, vous pouvez lui donner son propre réglage, qui prévaut sur le général.'; + + @override + String get tutorialPage3Headline => 'Enregistrez ce que vous écoutez'; + + @override + String get tutorialPage3Body => + 'Depuis la barre d\'outils du lecteur, « Enregistrer » sauvegarde le flux original. Retrouvez vos enregistrements dans Réglages › Enregistrements.'; + + @override + String get tutorialPage4Headline => 'Des alarmes qui s\'adaptent à vous'; + + @override + String get tutorialPage4Body => + 'Réveillez-vous avec votre station préférée, reportez de 3, 5 ou 10 minutes, et ajoutez des périodes de vacances pour que certaines alarmes se sautent d\'elles-mêmes.'; + + @override + String get tutorialPage5Headline => 'Vos favoris, aussi en voiture'; + + @override + String get tutorialPage5Body => + 'Connectez votre téléphone avec Android Auto et retrouvez Favoris, Toutes les stations, Vos stations et votre Musique locale, avec de grands boutons pensés pour la conduite.'; + + @override + String get tutorialPage6Headline => 'Se reconnecte toute seule'; + + @override + String get tutorialPage6Body => + 'Si le signal se coupe, PluriWave retente automatiquement et continue d\'afficher vos favoris enregistrés même sans connexion.'; + + @override + String get tutorialPage7Headline => 'Choisissez combien de temps reporter'; + + @override + String get tutorialPage7Body => + 'Quand une alarme sonne, il n\'y a pas un seul « reporter » : vous choisissez 3, 5 ou 10 minutes selon ce dont vous avez besoin à ce moment-là.'; + + @override + String get tutorialPage8Headline => + 'Vous ne la trouvez pas ? Ajoutez-la vous-même'; + + @override + String get tutorialPage8Body => + 'Dans « Vos stations » → Ajouter une station personnalisée, collez l\'URL du flux d\'une station absente des résultats de recherche. Elle est enregistrée dans « Vos stations », aussi disponible en voiture.'; + + @override + String get tutorialPage9Headline => 'Voilà, vous connaissez l\'essentiel'; + + @override + String get tutorialPage9BannerBody => + 'Pour revoir ce tutoriel quand vous le souhaitez : Réglages → Informations → Aide et tutoriel.'; @override String get indefiniteOption => 'Indéfinie'; diff --git a/lib/l10n/gen/app_localizations_hi.dart b/lib/l10n/gen/app_localizations_hi.dart index c6bf8fb..c7baf12 100644 --- a/lib/l10n/gen/app_localizations_hi.dart +++ b/lib/l10n/gen/app_localizations_hi.dart @@ -1411,8 +1411,78 @@ class AppLocalizationsHi extends AppLocalizations { String get helpTitle => 'मदद और ट्यूटोरियल'; @override - String get helpSubtitle => - 'PluriWave की सुविधाएँ, सुझाव और नया क्या है देखें।'; + String get helpSubtitle => '9 स्क्रीन · जब चाहें दोबारा देखें'; + + @override + String get tutorialSkipAction => 'छोड़ें'; + + @override + String get tutorialNextAction => 'अगला'; + + @override + String get tutorialPage1Headline => + 'अपने स्टेशन सहेजें और उन्हें समूहों में बाँटें'; + + @override + String get tutorialPage1Body => + 'किसी स्टेशन को सहेजने के लिए दिल के आइकॉन पर टैप करें। «आपके स्टेशन» में आप «हर सुबह» या «कार» जैसे समूह बना सकते हैं और उन्हें खींचकर पुनः क्रमबद्ध कर सकते हैं।'; + + @override + String get tutorialPage2Headline => + 'एक सामान्य इक्वलाइज़र, और हर स्टेशन के लिए एक अलग'; + + @override + String get tutorialPage2Body => + 'सेटिंग्स में आप सामान्य इक्वलाइज़र सेट करते हैं। और किसी खास स्टेशन को चलाते समय आप उसे अपनी खुद की सेटिंग दे सकते हैं, जो सामान्य सेटिंग पर प्राथमिकता रखती है।'; + + @override + String get tutorialPage3Headline => 'जो सुन रहे हैं उसे रिकॉर्ड करें'; + + @override + String get tutorialPage3Body => + 'प्लेयर की टूल ट्रे से, «रिकॉर्ड करें» मूल स्ट्रीम को सहेजता है। अपनी रिकॉर्डिंग सेटिंग्स › रिकॉर्डिंग में पाएँ।'; + + @override + String get tutorialPage4Headline => 'अलार्म जो आपके अनुसार ढलते हैं'; + + @override + String get tutorialPage4Body => + 'अपने पसंदीदा स्टेशन के साथ जागें, 3, 5 या 10 मिनट के लिए स्नूज़ करें, और छुट्टियों की अवधि जोड़ें ताकि कुछ अलार्म खुद-ब-खुद छूट जाएँ।'; + + @override + String get tutorialPage5Headline => 'आपके पसंदीदा, कार में भी'; + + @override + String get tutorialPage5Body => + 'अपने फ़ोन को Android Auto से जोड़ें और पाएँ पसंदीदा, सभी स्टेशन, आपके स्टेशन और आपका लोकल म्यूज़िक, ड्राइविंग के लिए बने बड़े बटनों के साथ।'; + + @override + String get tutorialPage6Headline => 'खुद ही फिर से जुड़ जाता है'; + + @override + String get tutorialPage6Body => + 'अगर सिग्नल कट जाए, तो PluriWave अपने आप फिर कोशिश करता है और बिना कनेक्शन के भी आपके सहेजे गए पसंदीदा दिखाता रहता है।'; + + @override + String get tutorialPage7Headline => 'चुनें कितनी देर के लिए स्नूज़ करना है'; + + @override + String get tutorialPage7Body => + 'जब कोई अलार्म बजता है, तो «स्नूज़» का कोई एक ही विकल्प नहीं होता: आप उस पल की ज़रूरत के अनुसार 3, 5 या 10 मिनट चुनते हैं।'; + + @override + String get tutorialPage8Headline => 'नहीं मिल रहा? खुद जोड़ें'; + + @override + String get tutorialPage8Body => + '«आपके स्टेशन» → कस्टम स्टेशन जोड़ें में, खोज में न मिलने वाले स्टेशन का स्ट्रीम URL पेस्ट करें। यह «आपके स्टेशन» में सहेजा जाता है और कार में भी उपलब्ध रहता है।'; + + @override + String get tutorialPage9Headline => 'हो गया, अब आप ज़रूरी बातें जानते हैं'; + + @override + String get tutorialPage9BannerBody => + 'इस ट्यूटोरियल को दोबारा देखने के लिए: सेटिंग्स → जानकारी → मदद और ट्यूटोरियल।'; @override String get indefiniteOption => 'अनिश्चित'; diff --git a/lib/l10n/gen/app_localizations_id.dart b/lib/l10n/gen/app_localizations_id.dart index 3a3c234..eee2b0a 100644 --- a/lib/l10n/gen/app_localizations_id.dart +++ b/lib/l10n/gen/app_localizations_id.dart @@ -1420,7 +1420,78 @@ class AppLocalizationsId extends AppLocalizations { String get helpTitle => 'Bantuan dan tutorial'; @override - String get helpSubtitle => 'Tinjau fitur, tips, dan hal baru di PluriWave.'; + String get helpSubtitle => '9 layar · lihat lagi kapan saja'; + + @override + String get tutorialSkipAction => 'Lewati'; + + @override + String get tutorialNextAction => 'Berikutnya'; + + @override + String get tutorialPage1Headline => 'Simpan stasiun Anda dan kelompokkan'; + + @override + String get tutorialPage1Body => + 'Ketuk ikon hati untuk menyimpan stasiun. Di «Stasiun Anda» Anda bisa membuat grup seperti «Setiap pagi» atau «Mobil» dan mengurutkannya ulang dengan menyeret.'; + + @override + String get tutorialPage2Headline => + 'Satu equalizer umum, dan satu lagi per stasiun'; + + @override + String get tutorialPage2Body => + 'Di Pengaturan, Anda menentukan equalizer umum. Dan dari pemutaran stasiun tertentu, Anda bisa memberinya pengaturan sendiri, yang lebih diutamakan daripada pengaturan umum.'; + + @override + String get tutorialPage3Headline => 'Rekam apa yang sedang Anda dengarkan'; + + @override + String get tutorialPage3Body => + 'Dari baki alat pemutar, «Rekam» menyimpan stream asli. Temukan rekaman Anda di Pengaturan › Rekaman.'; + + @override + String get tutorialPage4Headline => + 'Alarm yang menyesuaikan diri dengan Anda'; + + @override + String get tutorialPage4Body => + 'Bangun dengan stasiun favorit Anda, tunda 3, 5, atau 10 menit, dan tambahkan rentang liburan agar sebagian alarm melewati dirinya sendiri.'; + + @override + String get tutorialPage5Headline => 'Favorit Anda, juga di mobil'; + + @override + String get tutorialPage5Body => + 'Sambungkan ponsel Anda dengan Android Auto dan temukan Favorit, Semua stasiun, Stasiun Anda, dan Musik Lokal Anda, dengan tombol besar yang dirancang untuk berkendara.'; + + @override + String get tutorialPage6Headline => 'Tersambung ulang dengan sendirinya'; + + @override + String get tutorialPage6Body => + 'Jika sinyal terputus, PluriWave mencoba lagi secara otomatis dan tetap menampilkan favorit tersimpan Anda meski tanpa koneksi.'; + + @override + String get tutorialPage7Headline => 'Pilih berapa lama menunda'; + + @override + String get tutorialPage7Body => + 'Saat alarm berbunyi, tidak ada satu «tunda» saja: Anda memilih 3, 5, atau 10 menit sesuai yang Anda butuhkan saat itu.'; + + @override + String get tutorialPage8Headline => 'Tidak menemukannya? Tambahkan sendiri'; + + @override + String get tutorialPage8Body => + 'Di «Stasiun Anda» → Tambah stasiun khusus, tempel URL stream stasiun yang tidak ada di hasil pencarian. Stasiun ini disimpan di «Stasiun Anda», juga tersedia di mobil.'; + + @override + String get tutorialPage9Headline => 'Selesai, Anda sudah tahu yang penting'; + + @override + String get tutorialPage9BannerBody => + 'Untuk melihat tutorial ini lagi kapan saja: Pengaturan → Informasi → Bantuan dan tutorial.'; @override String get indefiniteOption => 'Tidak terbatas'; diff --git a/lib/l10n/gen/app_localizations_it.dart b/lib/l10n/gen/app_localizations_it.dart index ad1a334..8f9b018 100644 --- a/lib/l10n/gen/app_localizations_it.dart +++ b/lib/l10n/gen/app_localizations_it.dart @@ -1428,7 +1428,77 @@ class AppLocalizationsIt extends AppLocalizations { String get helpTitle => 'Aiuto e tutorial'; @override - String get helpSubtitle => 'Rivedi funzioni, consigli e novità di PluriWave.'; + String get helpSubtitle => '9 schermate · rivedilo quando vuoi'; + + @override + String get tutorialSkipAction => 'Salta'; + + @override + String get tutorialNextAction => 'Avanti'; + + @override + String get tutorialPage1Headline => 'Salva le tue emittenti e raggruppale'; + + @override + String get tutorialPage1Body => + 'Tocca il cuore per salvare un\'emittente. In «Le tue emittenti» puoi creare gruppi come «Ogni mattina» o «Auto» e riordinarle trascinandole.'; + + @override + String get tutorialPage2Headline => + 'Un equalizzatore di base e uno per emittente'; + + @override + String get tutorialPage2Body => + 'Nelle Impostazioni definisci l\'equalizzatore generale. E dalla riproduzione di un\'emittente specifica puoi darle un\'impostazione propria, che ha la priorità su quella generale.'; + + @override + String get tutorialPage3Headline => 'Registra ciò che stai ascoltando'; + + @override + String get tutorialPage3Body => + 'Dal vassoio degli strumenti del player, «Registra» salva lo stream originale. Trova le tue registrazioni in Impostazioni › Registrazioni.'; + + @override + String get tutorialPage4Headline => 'Sveglie che si adattano a te'; + + @override + String get tutorialPage4Body => + 'Svegliati con la tua emittente preferita, posticipa di 3, 5 o 10 minuti, e aggiungi intervalli di vacanza in modo che alcune sveglie si saltino da sole.'; + + @override + String get tutorialPage5Headline => 'I tuoi preferiti, anche in auto'; + + @override + String get tutorialPage5Body => + 'Collega il telefono con Android Auto e troverai Preferiti, Tutte le emittenti, Le tue emittenti e la tua Musica locale, con pulsanti grandi pensati per la guida.'; + + @override + String get tutorialPage6Headline => 'Si riconnette da sola'; + + @override + String get tutorialPage6Body => + 'Se il segnale cade, PluriWave riprova automaticamente e continua a mostrare i tuoi preferiti salvati anche senza connessione.'; + + @override + String get tutorialPage7Headline => 'Scegli quanto posticipare'; + + @override + String get tutorialPage7Body => + 'Quando suona una sveglia, non c\'è un solo «posticipa»: scegli 3, 5 o 10 minuti a seconda di cosa ti serve in quel momento.'; + + @override + String get tutorialPage8Headline => 'Non la trovi? Aggiungila tu'; + + @override + String get tutorialPage8Body => + 'In «Le tue emittenti» → Aggiungi emittente personalizzata incolla l\'URL dello stream di un\'emittente non presente nella ricerca. Viene salvata in «Le tue emittenti», disponibile anche in auto.'; + + @override + String get tutorialPage9Headline => 'Fatto, ora conosci l\'essenziale'; + + @override + String get tutorialPage9BannerBody => + 'Per rivedere questo tutorial quando vuoi: Impostazioni → Informazioni → Aiuto e tutorial.'; @override String get indefiniteOption => 'Indefinita'; diff --git a/lib/l10n/gen/app_localizations_ja.dart b/lib/l10n/gen/app_localizations_ja.dart index c6f045b..8d5dcf8 100644 --- a/lib/l10n/gen/app_localizations_ja.dart +++ b/lib/l10n/gen/app_localizations_ja.dart @@ -1368,7 +1368,76 @@ class AppLocalizationsJa extends AppLocalizations { String get helpTitle => 'ヘルプとチュートリアル'; @override - String get helpSubtitle => 'PluriWaveの機能、ヒント、新着情報を確認できます。'; + String get helpSubtitle => '全9画面・いつでも見返せます'; + + @override + String get tutorialSkipAction => 'スキップ'; + + @override + String get tutorialNextAction => '次へ'; + + @override + String get tutorialPage1Headline => 'お気に入りの局を保存してグループ分け'; + + @override + String get tutorialPage1Body => + 'ハートをタップして局を保存しましょう。「あなたの局」では「毎朝」や「車」などのグループを作り、ドラッグして並べ替えられます。'; + + @override + String get tutorialPage2Headline => '基本のイコライザーと局ごとのイコライザー'; + + @override + String get tutorialPage2Body => + '設定で全体のイコライザーを決められます。特定の局を再生中は、その局専用の設定を適用でき、全体設定より優先されます。'; + + @override + String get tutorialPage3Headline => '聴いている番組を録音'; + + @override + String get tutorialPage3Body => + 'プレーヤーのツールトレイから「録音」をタップすると、元のストリームが保存されます。録音は設定›録音で確認できます。'; + + @override + String get tutorialPage4Headline => 'あなたに合わせてくれるアラーム'; + + @override + String get tutorialPage4Body => + 'お気に入りの局で目覚め、3分・5分・10分でスヌーズでき、休暇期間を追加すれば一部のアラームを自動でスキップできます。'; + + @override + String get tutorialPage5Headline => 'お気に入りは車でも'; + + @override + String get tutorialPage5Body => + 'スマートフォンをAndroid Autoに接続すると、お気に入り、すべての局、あなたの局、ローカルミュージックが、運転向けの大きなボタンで使えます。'; + + @override + String get tutorialPage6Headline => '自動で再接続'; + + @override + String get tutorialPage6Body => + '電波が途切れても、PluriWaveは自動的に再試行し、接続がなくても保存済みのお気に入りを表示し続けます。'; + + @override + String get tutorialPage7Headline => 'スヌーズ時間を選べる'; + + @override + String get tutorialPage7Body => + 'アラームが鳴ったとき、「スヌーズ」は一つだけではありません。3分・5分・10分から、その時必要な時間を選べます。'; + + @override + String get tutorialPage8Headline => '見つからない?自分で追加'; + + @override + String get tutorialPage8Body => + '「あなたの局」→カスタム局を追加で、検索にない局のストリームURLを貼り付けられます。「あなたの局」に保存され、車でも利用できます。'; + + @override + String get tutorialPage9Headline => '完了、基本はこれで押さえました'; + + @override + String get tutorialPage9BannerBody => + 'このチュートリアルはいつでも再確認できます:設定 → 情報 → ヘルプとチュートリアル。'; @override String get indefiniteOption => '無期限'; diff --git a/lib/l10n/gen/app_localizations_pt.dart b/lib/l10n/gen/app_localizations_pt.dart index 88f3343..a562d30 100644 --- a/lib/l10n/gen/app_localizations_pt.dart +++ b/lib/l10n/gen/app_localizations_pt.dart @@ -1416,7 +1416,77 @@ class AppLocalizationsPt extends AppLocalizations { String get helpTitle => 'Ajuda e tutorial'; @override - String get helpSubtitle => 'Revê funções, dicas e novidades do PluriWave.'; + String get helpSubtitle => '9 ecrãs · reveja quando quiser'; + + @override + String get tutorialSkipAction => 'Pular'; + + @override + String get tutorialNextAction => 'Avançar'; + + @override + String get tutorialPage1Headline => 'Guarde as suas estações e agrupe-as'; + + @override + String get tutorialPage1Body => + 'Toque no coração para guardar uma estação. Em «Suas estações» pode criar grupos como «Todas as manhãs» ou «Carro» e reordená-las arrastando.'; + + @override + String get tutorialPage2Headline => + 'Um equalizador geral e outro por estação'; + + @override + String get tutorialPage2Body => + 'Em Definições define o equalizador geral. E, ao reproduzir uma estação específica, pode dar-lhe o seu próprio ajuste, que prevalece sobre o geral.'; + + @override + String get tutorialPage3Headline => 'Grave o que está a ouvir'; + + @override + String get tutorialPage3Body => + 'Na bandeja de ferramentas do leitor, «Gravar» guarda o stream original. Encontre as suas gravações em Definições › Gravações.'; + + @override + String get tutorialPage4Headline => 'Alarmes que se adaptam a si'; + + @override + String get tutorialPage4Body => + 'Acorde com a sua estação favorita, adie 3, 5 ou 10 minutos, e adicione períodos de férias para que alguns alarmes se saltem sozinhos.'; + + @override + String get tutorialPage5Headline => 'Os seus favoritos, também no carro'; + + @override + String get tutorialPage5Body => + 'Ligue o telemóvel ao Android Auto e encontre Favoritos, Todas as estações, Suas estações e a sua Música local, com botões grandes pensados para conduzir.'; + + @override + String get tutorialPage6Headline => 'Reconecta-se sozinho'; + + @override + String get tutorialPage6Body => + 'Se o sinal cair, o PluriWave tenta novamente de forma automática e continua a mostrar os seus favoritos guardados mesmo sem ligação.'; + + @override + String get tutorialPage7Headline => 'Escolha quanto tempo adiar'; + + @override + String get tutorialPage7Body => + 'Quando um alarme toca, não existe um único «adiar»: escolhe 3, 5 ou 10 minutos conforme o que precisar nesse momento.'; + + @override + String get tutorialPage8Headline => 'Não a encontra? Adicione-a você mesmo'; + + @override + String get tutorialPage8Body => + 'Em «Suas estações» → Adicionar estação personalizada, cole o URL do stream de uma estação que não esteja na pesquisa. Fica guardada em «Suas estações», também disponível no carro.'; + + @override + String get tutorialPage9Headline => 'Pronto, já conhece o essencial'; + + @override + String get tutorialPage9BannerBody => + 'Para rever este tutorial quando quiser: Definições → Informação → Ajuda e tutorial.'; @override String get indefiniteOption => 'Indefinida'; diff --git a/lib/l10n/gen/app_localizations_ru.dart b/lib/l10n/gen/app_localizations_ru.dart index aceb85b..25ce7f5 100644 --- a/lib/l10n/gen/app_localizations_ru.dart +++ b/lib/l10n/gen/app_localizations_ru.dart @@ -1420,7 +1420,79 @@ class AppLocalizationsRu extends AppLocalizations { String get helpTitle => 'Помощь и руководство'; @override - String get helpSubtitle => 'Посмотрите функции, советы и новости PluriWave.'; + String get helpSubtitle => '9 экранов · смотрите снова в любое время'; + + @override + String get tutorialSkipAction => 'Пропустить'; + + @override + String get tutorialNextAction => 'Далее'; + + @override + String get tutorialPage1Headline => 'Сохраняйте станции и группируйте их'; + + @override + String get tutorialPage1Body => + 'Нажмите на сердечко, чтобы сохранить станцию. В разделе «Ваши станции» можно создавать группы, например «Каждое утро» или «Машина», и менять порядок перетаскиванием.'; + + @override + String get tutorialPage2Headline => + 'Общий эквалайзер и отдельный для каждой станции'; + + @override + String get tutorialPage2Body => + 'В настройках вы задаёте общий эквалайзер. А во время воспроизведения конкретной станции можно задать для неё собственную настройку — она будет иметь приоритет над общей.'; + + @override + String get tutorialPage3Headline => 'Записывайте то, что слушаете'; + + @override + String get tutorialPage3Body => + 'На панели инструментов плеера кнопка «Запись» сохраняет исходный поток. Ваши записи хранятся в разделе Настройки › Записи.'; + + @override + String get tutorialPage4Headline => + 'Будильники, которые подстраиваются под вас'; + + @override + String get tutorialPage4Body => + 'Просыпайтесь под любимую станцию, откладывайте на 3, 5 или 10 минут и добавляйте периоды отпуска, чтобы некоторые будильники пропускались сами.'; + + @override + String get tutorialPage5Headline => + 'Ваши избранные станции — и в машине тоже'; + + @override + String get tutorialPage5Body => + 'Подключите телефон через Android Auto, и вы найдёте Избранное, Все станции, Ваши станции и вашу локальную музыку с крупными кнопками, удобными за рулём.'; + + @override + String get tutorialPage6Headline => 'Переподключается сам'; + + @override + String get tutorialPage6Body => + 'Если сигнал пропадает, PluriWave автоматически повторяет попытку и продолжает показывать сохранённые избранные станции даже без подключения.'; + + @override + String get tutorialPage7Headline => 'Выбирайте, на сколько отложить'; + + @override + String get tutorialPage7Body => + 'Когда звонит будильник, нет единственного варианта «отложить»: выбирайте 3, 5 или 10 минут — в зависимости от того, что нужно именно сейчас.'; + + @override + String get tutorialPage8Headline => 'Не нашли станцию? Добавьте её сами'; + + @override + String get tutorialPage8Body => + 'В разделе «Ваши станции» → Добавить свою станцию вставьте URL потока станции, которой нет в поиске. Она сохранится в «Ваши станции» и будет доступна и в машине.'; + + @override + String get tutorialPage9Headline => 'Готово, теперь вы знаете самое важное'; + + @override + String get tutorialPage9BannerBody => + 'Чтобы посмотреть этот урок ещё раз: Настройки → Информация → Помощь и руководство.'; @override String get indefiniteOption => 'Без ограничения'; diff --git a/lib/l10n/gen/app_localizations_zh.dart b/lib/l10n/gen/app_localizations_zh.dart index c5a2dde..3e53ca2 100644 --- a/lib/l10n/gen/app_localizations_zh.dart +++ b/lib/l10n/gen/app_localizations_zh.dart @@ -1363,7 +1363,75 @@ class AppLocalizationsZh extends AppLocalizations { String get helpTitle => '帮助和教程'; @override - String get helpSubtitle => '查看 PluriWave 的功能、技巧和新内容。'; + String get helpSubtitle => '共9屏 · 随时可重新查看'; + + @override + String get tutorialSkipAction => '跳过'; + + @override + String get tutorialNextAction => '下一步'; + + @override + String get tutorialPage1Headline => '保存并整理你的电台'; + + @override + String get tutorialPage1Body => + '点击心形图标即可保存电台。在“你的电台”中,你可以创建“每天早上”或“车载”等分组,并通过拖动重新排序。'; + + @override + String get tutorialPage2Headline => '一个通用均衡器,外加每个电台专属的均衡器'; + + @override + String get tutorialPage2Body => + '在设置中可以调整通用均衡器。播放某个电台时,你还可以为它单独设置均衡器,该设置优先于通用设置。'; + + @override + String get tutorialPage3Headline => '录制正在收听的内容'; + + @override + String get tutorialPage3Body => + '在播放器工具栏中点击“录制”,即可保存原始音频流。录音内容可在 设置 › 录音 中查看。'; + + @override + String get tutorialPage4Headline => '会迁就你的闹钟'; + + @override + String get tutorialPage4Body => + '用喜欢的电台唤醒自己,可以推迟3分钟、5分钟或10分钟,还能添加假期时间段,让部分闹钟自动跳过。'; + + @override + String get tutorialPage5Headline => '收藏的电台,车载也能用'; + + @override + String get tutorialPage5Body => + '将手机连接到Android Auto,即可看到收藏、全部电台、你的电台和本地音乐,大按钮专为驾驶设计。'; + + @override + String get tutorialPage6Headline => '自动重新连接'; + + @override + String get tutorialPage6Body => + '信号中断时,PluriWave会自动重试连接,即使暂时没有网络也会继续显示已保存的收藏电台。'; + + @override + String get tutorialPage7Headline => '自选推迟时长'; + + @override + String get tutorialPage7Body => + '闹钟响起时,“推迟”并非只有一种选择:你可以根据当下需要选择推迟3分钟、5分钟或10分钟。'; + + @override + String get tutorialPage8Headline => '找不到?自己添加'; + + @override + String get tutorialPage8Body => + '在“你的电台”→添加自定义电台中,粘贴搜索结果里没有的电台的流媒体URL即可。它会保存在“你的电台”中,车载模式下同样可用。'; + + @override + String get tutorialPage9Headline => '完成,你已经了解核心功能'; + + @override + String get tutorialPage9BannerBody => '想随时重新观看本教程:设置 → 信息 → 帮助与教程。'; @override String get indefiniteOption => '不限时'; diff --git a/lib/pantallas/ajustes/pantalla_ajustes_info.dart b/lib/pantallas/ajustes/pantalla_ajustes_info.dart index 6447709..ac6f00f 100644 --- a/lib/pantallas/ajustes/pantalla_ajustes_info.dart +++ b/lib/pantallas/ajustes/pantalla_ajustes_info.dart @@ -7,8 +7,8 @@ import '../../l10n/gen/app_localizations.dart'; import '../../widgets/pluri_glass_surface.dart'; import '../../widgets/pluri_icon.dart'; import '../../widgets/pluri_layout.dart'; -import '../../widgets/pluri_onboarding_dialog.dart'; import '../../widgets/pluri_push_scaffold.dart'; +import '../pantalla_tutorial_ayuda.dart'; /// APLICACIÓN group · "Info" (design ADR-3). Body moved verbatim from the /// former `_SeccionInfo` in `pantalla_ajustes.dart`. Unlike the other four @@ -86,7 +86,15 @@ class _CuerpoInfo extends StatelessWidget { title: Text(AppLocalizations.of(ctx).helpTitle), subtitle: Text(AppLocalizations.of(ctx).helpSubtitle), trailing: const Icon(Icons.chevron_right_rounded), - onTap: () => PluriOnboardingDialog.mostrar(ctx), + onTap: + () => Navigator.of(ctx).push( + MaterialPageRoute( + builder: + (_) => const PantallaTutorialAyuda( + primerArranque: false, + ), + ), + ), ), ListTile( contentPadding: EdgeInsets.zero, diff --git a/lib/pantallas/pantalla_tutorial_ayuda.dart b/lib/pantallas/pantalla_tutorial_ayuda.dart new file mode 100644 index 0000000..5dc1d00 --- /dev/null +++ b/lib/pantallas/pantalla_tutorial_ayuda.dart @@ -0,0 +1,363 @@ +import 'package:flutter/material.dart'; + +import '../l10n/gen/app_localizations.dart'; +import '../servicios/servicio_tutorial_ayuda.dart'; +import '../tema/pluriwave_theme.dart'; +import '../tema/pluriwave_tokens.dart'; + +/// 9-screen help/tutorial carousel (mockup screens 5b..5h, reading order +/// 1..9). Reachable two ways: +/// - [mostrarSiProcede]: the genuine first-launch sequence in `app.dart`, +/// run once ever (both fresh installs AND existing installs upgrading to +/// this version), via [ServicioTutorialAyuda]'s plain one-time flag. +/// - Manually from Ajustes > Info > "Ayuda y tutorial", constructed directly +/// with `primerArranque: false`. +/// +/// [primerArranque] only changes the LAST page's CTA label -- "Empezar a +/// escuchar" on a first-launch entry, "Cerrar" otherwise. Every other +/// behaviour (Saltar pops immediately, Siguiente advances) is identical +/// regardless of entry point; both cases simply pop the route when +/// finished, letting whatever screen is already mounted underneath show. +class PantallaTutorialAyuda extends StatefulWidget { + const PantallaTutorialAyuda({super.key, required this.primerArranque}); + + final bool primerArranque; + + static final ServicioTutorialAyuda _servicio = ServicioTutorialAyuda(); + + static const int cantidadPaginas = 9; + + /// Shows this carousel once, on the genuine first-launch sequence, then + /// never again. Mirrors `PantallaBienvenida.mostrarSiProcede`'s shape + /// (check-then-show-then-mark-seen). + static Future mostrarSiProcede(BuildContext context) async { + if (!await _servicio.debeMostrarTutorial()) return; + if (!context.mounted) return; + await Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => const PantallaTutorialAyuda(primerArranque: true), + ), + ); + await _servicio.marcarTutorialVisto(); + } + + @override + State createState() => _PantallaTutorialAyudaState(); +} + +class _PantallaTutorialAyudaState extends State { + final _controller = PageController(); + int _pagina = 0; + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + bool get _esUltimaPagina => + _pagina == PantallaTutorialAyuda.cantidadPaginas - 1; + + void _saltar() => Navigator.of(context).pop(); + + void _siguiente() { + if (_esUltimaPagina) { + Navigator.of(context).pop(); + return; + } + _controller.nextPage( + duration: const Duration(milliseconds: 260), + curve: Curves.easeOutCubic, + ); + } + + @override + Widget build(BuildContext context) { + final l10n = AppLocalizations.of(context); + final paginas = _construirPaginas(l10n); + + return Scaffold( + body: SafeArea( + child: Column( + children: [ + SizedBox( + height: 48, + child: Align( + alignment: Alignment.centerRight, + child: + _esUltimaPagina + ? null + : Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: TextButton( + onPressed: _saltar, + child: Text(l10n.tutorialSkipAction), + ), + ), + ), + ), + Expanded( + child: PageView.builder( + controller: _controller, + itemCount: PantallaTutorialAyuda.cantidadPaginas, + onPageChanged: (indice) => setState(() => _pagina = indice), + itemBuilder: + (context, indice) => + TarjetaPaginaTutorial(datos: paginas[indice]), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + for ( + var i = 0; + i < PantallaTutorialAyuda.cantidadPaginas; + i++ + ) + PuntoIndicadorTutorial(activo: i == _pagina), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(24, 0, 24, 24), + child: SizedBox( + height: 58, + width: double.infinity, + child: FilledButton( + onPressed: _siguiente, + style: FilledButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + ), + ), + child: Text( + _esUltimaPagina + ? (widget.primerArranque + ? l10n.welcomeCtaLabel + : l10n.closeAction) + : l10n.tutorialNextAction, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w800, + ), + ), + ), + ), + ), + ], + ), + ), + ); + } + + List _construirPaginas(AppLocalizations l10n) { + final t = PluriWaveTokens.dark; + return [ + DatosPaginaTutorial( + icono: Icons.favorite_rounded, + color: t.electricMagenta, + titulo: l10n.tutorialPage1Headline, + cuerpo: l10n.tutorialPage1Body, + ), + DatosPaginaTutorial( + icono: Icons.equalizer_rounded, + color: t.liveGreen, + titulo: l10n.tutorialPage2Headline, + cuerpo: l10n.tutorialPage2Body, + ), + DatosPaginaTutorial( + icono: Icons.mic_rounded, + color: t.warmCoral, + titulo: l10n.tutorialPage3Headline, + cuerpo: l10n.tutorialPage3Body, + ), + DatosPaginaTutorial( + icono: Icons.alarm_rounded, + color: t.offlineAccent, + titulo: l10n.tutorialPage4Headline, + cuerpo: l10n.tutorialPage4Body, + ), + DatosPaginaTutorial( + icono: Icons.directions_car_rounded, + color: PluriWaveTokens.skyBlue, + titulo: l10n.tutorialPage5Headline, + cuerpo: l10n.tutorialPage5Body, + ), + DatosPaginaTutorial( + icono: Icons.wifi_tethering_rounded, + color: t.liveGreen, + titulo: l10n.tutorialPage6Headline, + cuerpo: l10n.tutorialPage6Body, + ), + DatosPaginaTutorial( + icono: Icons.snooze_rounded, + color: t.warmCoral, + titulo: l10n.tutorialPage7Headline, + cuerpo: l10n.tutorialPage7Body, + ), + DatosPaginaTutorial( + icono: Icons.add_link_rounded, + color: PluriWaveTokens.skyBlue, + titulo: l10n.tutorialPage8Headline, + cuerpo: l10n.tutorialPage8Body, + ), + DatosPaginaTutorial( + icono: Icons.check_circle_rounded, + color: t.electricMagenta, + titulo: l10n.tutorialPage9Headline, + // Last page only: the "watch it again" reminder banner (design + // ADR text, mockup screen 5h). No progress-dot advancement beyond + // this page -- it is the final one. + bannerCuerpo: l10n.tutorialPage9BannerBody, + ), + ]; + } +} + +/// Content for a single carousel page: icon badge, headline, body, and -- +/// only on the last page -- the "watch it again" reminder banner. +class DatosPaginaTutorial { + const DatosPaginaTutorial({ + required this.icono, + required this.color, + required this.titulo, + this.cuerpo, + this.bannerCuerpo, + }); + + final IconData icono; + final Color color; + final String titulo; + + /// Body copy below the headline. `null` on the last page (mockup screen + /// 5h), which shows only the headline plus [bannerCuerpo] -- no separate + /// body paragraph. + final String? cuerpo; + final String? bannerCuerpo; +} + +/// One carousel page: a 150x150 rounded-square icon badge, headline, body, +/// and -- when [DatosPaginaTutorial.bannerCuerpo] is set -- the reminder +/// banner. Public (not `_TarjetaPagina`) so tests can target pages by type, +/// same reason `FilaCaracteristicaBienvenida` is public. +class TarjetaPaginaTutorial extends StatelessWidget { + const TarjetaPaginaTutorial({super.key, required this.datos}); + + final DatosPaginaTutorial datos; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 150, + height: 150, + decoration: BoxDecoration( + color: datos.color.withValues(alpha: 0.13), + borderRadius: BorderRadius.circular(32), + ), + child: Icon(datos.icono, size: 72, color: datos.color), + ), + const SizedBox(height: 32), + Text( + datos.titulo, + textAlign: TextAlign.center, + style: theme.textTheme.headlineSmall?.copyWith( + fontSize: 24, + fontWeight: FontWeight.w800, + letterSpacing: -0.4, + height: 1.15, + ), + ), + if (datos.cuerpo case final cuerpo?) ...[ + const SizedBox(height: 12), + Text( + cuerpo, + textAlign: TextAlign.center, + style: theme.textTheme.bodyMedium?.copyWith( + fontSize: 14, + height: 1.5, + color: theme.colorScheme.onSurface.withValues(alpha: 0.7), + ), + ), + ], + if (datos.bannerCuerpo case final bannerCuerpo?) ...[ + const SizedBox(height: 24), + _BannerRecordatorio(texto: bannerCuerpo), + ], + ], + ), + ); + } +} + +class _BannerRecordatorio extends StatelessWidget { + const _BannerRecordatorio({required this.texto}); + + final String texto; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Container( + padding: const EdgeInsets.all(14), + decoration: BoxDecoration( + color: Colors.white.withValues(alpha: 0.06), + borderRadius: BorderRadius.circular(16), + border: Border.all(color: Colors.white.withValues(alpha: 0.1)), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.info_outline_rounded, + size: 20, + color: theme.colorScheme.onSurface.withValues(alpha: 0.7), + ), + const SizedBox(width: 10), + Expanded( + child: Text( + texto, + style: theme.textTheme.bodySmall?.copyWith( + fontSize: 12.5, + height: 1.4, + color: theme.colorScheme.onSurface.withValues(alpha: 0.72), + ), + ), + ), + ], + ), + ); + } +} + +/// One dot in the 9-dot progress indicator: wider and teal when [activo], +/// small and translucent otherwise. Public so tests can assert "exactly 9 +/// dots" via `find.byType`. +class PuntoIndicadorTutorial extends StatelessWidget { + const PuntoIndicadorTutorial({super.key, required this.activo}); + + final bool activo; + + @override + Widget build(BuildContext context) { + final t = context.pluriTokens; + return AnimatedContainer( + duration: const Duration(milliseconds: 200), + margin: const EdgeInsets.symmetric(horizontal: 3), + width: activo ? 24 : 8, + height: 8, + decoration: BoxDecoration( + color: + activo ? t.electricMagenta : Colors.white.withValues(alpha: 0.24), + borderRadius: BorderRadius.circular(4), + ), + ); + } +} diff --git a/lib/servicios/servicio_tutorial_ayuda.dart b/lib/servicios/servicio_tutorial_ayuda.dart new file mode 100644 index 0000000..5cd5d81 --- /dev/null +++ b/lib/servicios/servicio_tutorial_ayuda.dart @@ -0,0 +1,32 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +/// Persists whether the 9-screen help/tutorial carousel (`PantallaTutorialAyuda`) +/// has already been shown, so it renders once on the genuine first-run +/// sequence rather than on every launch. +/// +/// Same injectable-`SharedPreferences`, versioned-key convention as +/// `ServicioBienvenida` -- a plain one-time boolean flag, not a per-app-version +/// "due again" scheme like `ServicioContenidoApp` uses: no existing user has +/// this flag set yet, regardless of whether they are a fresh install or an +/// upgrade, so a single flag already satisfies "show once, ever". +class ServicioTutorialAyuda { + ServicioTutorialAyuda({SharedPreferences? prefs}) : _prefs = prefs; + + static const _keyTutorialVisto = 'pluri_tutorial_visto_v1'; + + final SharedPreferences? _prefs; + + /// Injected startup instance (S3-R4); getInstance() is only a fallback. + Future _resolverPrefs() async => + _prefs ?? SharedPreferences.getInstance(); + + Future debeMostrarTutorial() async { + final prefs = await _resolverPrefs(); + return !(prefs.getBool(_keyTutorialVisto) ?? false); + } + + Future marcarTutorialVisto() async { + final prefs = await _resolverPrefs(); + await prefs.setBool(_keyTutorialVisto, true); + } +} diff --git a/test/app_test.dart b/test/app_test.dart index 9e2ae3e..31d5150 100644 --- a/test/app_test.dart +++ b/test/app_test.dart @@ -20,4 +20,53 @@ void main() { 'PluriRootHeader inside its content instead', ); }); + + test('the first-launch sequence runs the welcome screen, then the tutorial ' + 'carousel, then the recurring what-is-new dialog, in that order', () { + // `_PaginaPrincipal` is library-private and its + // `_mostrarFlujoPrimerLanzamiento` constructs real platform-backed + // services, so it cannot be safely widget-tested here (same + // constraint as the AppBar guard above). This is a fast source-level + // ordering guard instead: PantallaBienvenida.mostrarSiProcede must + // run before PantallaTutorialAyuda.mostrarSiProcede, which must run + // before the unrelated, pre-existing _mostrarOnboardingInicial() call + // -- so the tutorial shows once on every launch sequence (fresh + // installs AND existing installs upgrading to this version) without + // ever racing the welcome screen or the what's-new dialog. + final source = File('lib/app.dart').readAsStringSync(); + + final indiceBienvenida = source.indexOf( + 'PantallaBienvenida.mostrarSiProcede', + ); + final indiceTutorial = source.indexOf( + 'PantallaTutorialAyuda.mostrarSiProcede', + ); + final indiceOnboarding = source.indexOf('_mostrarOnboardingInicial()'); + + expect( + indiceBienvenida, + greaterThanOrEqualTo(0), + reason: 'PantallaBienvenida.mostrarSiProcede must still be called', + ); + expect( + indiceTutorial, + greaterThanOrEqualTo(0), + reason: 'PantallaTutorialAyuda.mostrarSiProcede must be wired in', + ); + expect( + indiceOnboarding, + greaterThanOrEqualTo(0), + reason: '_mostrarOnboardingInicial() must still be called', + ); + expect( + indiceBienvenida, + lessThan(indiceTutorial), + reason: 'the welcome screen must run before the tutorial carousel', + ); + expect( + indiceTutorial, + lessThan(indiceOnboarding), + reason: 'the tutorial carousel must run before the what-is-new dialog', + ); + }); } diff --git a/test/pantallas/ajustes/pantalla_ajustes_info_test.dart b/test/pantallas/ajustes/pantalla_ajustes_info_test.dart index 93885fa..ecc9d90 100644 --- a/test/pantallas/ajustes/pantalla_ajustes_info_test.dart +++ b/test/pantallas/ajustes/pantalla_ajustes_info_test.dart @@ -5,6 +5,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:pluriwave/estado/estado_radio.dart'; import 'package:pluriwave/l10n/gen/app_localizations.dart'; import 'package:pluriwave/pantallas/ajustes/pantalla_ajustes_info.dart'; +import 'package:pluriwave/pantallas/pantalla_tutorial_ayuda.dart'; import 'package:pluriwave/widgets/pluri_push_scaffold.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -98,4 +99,24 @@ void main() { expect(find.text('Help and tutorial'), findsOneWidget); }, ); + + testWidgets('tapping "Help and tutorial" opens the tutorial carousel with ' + 'primerArranque: false (so its last page reads "Close", not ' + '"Start listening")', (tester) async { + _suppressListTileInkAssertion(); + final estado = await crearEstado(); + addTearDown(estado.dispose); + + await tester.pumpWidget(buildScreen(estado)); + await tester.pump(); + await tester.pump(const Duration(milliseconds: 100)); + + await tester.tap(find.text('Help and tutorial')); + await tester.pumpAndSettle(); + + final pantalla = tester.widget( + find.byType(PantallaTutorialAyuda), + ); + expect(pantalla.primerArranque, isFalse); + }); } diff --git a/test/pantallas/pantalla_tutorial_ayuda_primer_lanzamiento_test.dart b/test/pantallas/pantalla_tutorial_ayuda_primer_lanzamiento_test.dart new file mode 100644 index 0000000..38fcfe9 --- /dev/null +++ b/test/pantallas/pantalla_tutorial_ayuda_primer_lanzamiento_test.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pluriwave/l10n/gen/app_localizations.dart'; +import 'package:pluriwave/pantallas/pantalla_tutorial_ayuda.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +/// `PantallaTutorialAyuda.mostrarSiProcede` wires the 9-screen help/tutorial +/// carousel into the genuine first-launch flow (`app.dart`), between the +/// welcome screen and the recurring "what's new" dialog. This must show +/// once -- to both a genuinely fresh install AND an existing install that +/// already has other, unrelated flags persisted (e.g. the welcome screen +/// already marked seen) -- and never again after that. +Widget _appConDisparador(GlobalKey navigatorKey) { + return MaterialApp( + navigatorKey: navigatorKey, + locale: const Locale('es'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: Builder( + builder: + (context) => Scaffold( + body: Center( + child: ElevatedButton( + onPressed: + () => PantallaTutorialAyuda.mostrarSiProcede(context), + child: const Text('disparar'), + ), + ), + ), + ), + ); +} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets( + 'first launch (no seen flag persisted) shows the tutorial carousel', + (tester) async { + SharedPreferences.setMockInitialValues({}); + final navigatorKey = GlobalKey(); + + await tester.pumpWidget(_appConDisparador(navigatorKey)); + await tester.tap(find.text('disparar')); + await tester.pumpAndSettle(); + + expect(find.byType(PantallaTutorialAyuda), findsOneWidget); + }, + ); + + testWidgets('an existing install with unrelated flags already set (e.g. the ' + 'welcome screen already seen) but never this one still shows it', ( + tester, + ) async { + SharedPreferences.setMockInitialValues({'pluri_bienvenida_vista_v1': true}); + final navigatorKey = GlobalKey(); + + await tester.pumpWidget(_appConDisparador(navigatorKey)); + await tester.tap(find.text('disparar')); + await tester.pumpAndSettle(); + + expect(find.byType(PantallaTutorialAyuda), findsOneWidget); + }); + + testWidgets( + 'second launch (seen flag already persisted) does not show it again', + (tester) async { + SharedPreferences.setMockInitialValues({'pluri_tutorial_visto_v1': true}); + final navigatorKey = GlobalKey(); + + await tester.pumpWidget(_appConDisparador(navigatorKey)); + await tester.tap(find.text('disparar')); + await tester.pumpAndSettle(); + + expect(find.byType(PantallaTutorialAyuda), findsNothing); + }, + ); + + testWidgets('showing it once persists the flag so a later check in the same ' + 'session skips it', (tester) async { + SharedPreferences.setMockInitialValues({}); + final navigatorKey = GlobalKey(); + + await tester.pumpWidget(_appConDisparador(navigatorKey)); + await tester.tap(find.text('disparar')); + await tester.pumpAndSettle(); + expect(find.byType(PantallaTutorialAyuda), findsOneWidget); + + // Dismiss it the same way "Saltar"/the last CTA does (a plain pop), + // simulating the carousel being resolved before the next check happens. + navigatorKey.currentState!.pop(); + await tester.pumpAndSettle(); + + await tester.tap(find.text('disparar')); + await tester.pumpAndSettle(); + expect(find.byType(PantallaTutorialAyuda), findsNothing); + }); +} diff --git a/test/pantallas/pantalla_tutorial_ayuda_test.dart b/test/pantallas/pantalla_tutorial_ayuda_test.dart new file mode 100644 index 0000000..6ec51c5 --- /dev/null +++ b/test/pantallas/pantalla_tutorial_ayuda_test.dart @@ -0,0 +1,240 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pluriwave/l10n/gen/app_localizations.dart'; +import 'package:pluriwave/pantallas/pantalla_tutorial_ayuda.dart'; + +/// The 9-screen help/tutorial carousel (`PantallaTutorialAyuda`). Content +/// spec: mockup screens 5b..5h (reading order 1..9), each with an icon +/// badge, a headline, a body, a 9-dot progress indicator, a "Siguiente" +/// (Next) button, and -- on every page except the last -- a "Saltar" +/// (Skip) affordance. The last page's CTA reads "Empezar a escuchar" on a +/// first-launch entry, or "Cerrar" when reached manually from Ajustes +/// (`primerArranque` constructor param), and it drops "Saltar" entirely. +Widget _app({required bool primerArranque}) { + return MaterialApp( + locale: const Locale('es'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: PantallaTutorialAyuda(primerArranque: primerArranque), + ); +} + +/// The 9 expected headlines, in the mandated reading order (mockup ids +/// 5b, 5c, 5d, 5e, 5f, 5g, 5h1, 5h2, 5h). +List _headlinesEsperados(AppLocalizations l10n) => [ + l10n.tutorialPage1Headline, + l10n.tutorialPage2Headline, + l10n.tutorialPage3Headline, + l10n.tutorialPage4Headline, + l10n.tutorialPage5Headline, + l10n.tutorialPage6Headline, + l10n.tutorialPage7Headline, + l10n.tutorialPage8Headline, + l10n.tutorialPage9Headline, +]; + +void main() { + final l10n = lookupAppLocalizations(const Locale('es')); + + testWidgets('renders exactly 9 pages, one dot per page', (tester) async { + await tester.pumpWidget(_app(primerArranque: true)); + await tester.pump(); + + final pageView = tester.widget(find.byType(PageView)); + expect(pageView.controller!.hasClients, isTrue); + + expect( + find.byType(PuntoIndicadorTutorial), + findsNWidgets(9), + reason: 'exactly 9 dots, one per page', + ); + }); + + testWidgets( + 'the 9 pages carry the right headlines, in the mandated reading order', + (tester) async { + await tester.pumpWidget(_app(primerArranque: true)); + await tester.pump(); + + final pageView = tester.widget(find.byType(PageView)); + final controller = pageView.controller!; + final esperados = _headlinesEsperados(l10n); + + for (var i = 0; i < esperados.length; i++) { + controller.jumpToPage(i); + await tester.pump(); + expect( + find.text(esperados[i]), + findsOneWidget, + reason: 'page $i should show "${esperados[i]}"', + ); + } + }, + ); + + testWidgets('Saltar pops immediately from the first page', (tester) async { + final navigatorKey = GlobalKey(); + await tester.pumpWidget( + MaterialApp( + navigatorKey: navigatorKey, + locale: const Locale('es'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: const Scaffold(body: Center(child: Text('home stand-in'))), + ), + ); + + unawaited( + navigatorKey.currentState!.push( + MaterialPageRoute( + builder: (_) => const PantallaTutorialAyuda(primerArranque: true), + ), + ), + ); + await tester.pumpAndSettle(); + expect(find.byType(PantallaTutorialAyuda), findsOneWidget); + + await tester.tap(find.text(l10n.tutorialSkipAction)); + await tester.pumpAndSettle(); + + expect(find.byType(PantallaTutorialAyuda), findsNothing); + expect(find.text('home stand-in'), findsOneWidget); + }); + + testWidgets( + 'Saltar pops immediately from a middle page, not only the first', + (tester) async { + final navigatorKey = GlobalKey(); + await tester.pumpWidget( + MaterialApp( + navigatorKey: navigatorKey, + locale: const Locale('es'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: const Scaffold(body: Center(child: Text('home stand-in'))), + ), + ); + + unawaited( + navigatorKey.currentState!.push( + MaterialPageRoute( + builder: (_) => const PantallaTutorialAyuda(primerArranque: true), + ), + ), + ); + await tester.pumpAndSettle(); + + final pageView = tester.widget(find.byType(PageView)); + pageView.controller!.jumpToPage(3); + await tester.pump(); + + await tester.tap(find.text(l10n.tutorialSkipAction)); + await tester.pumpAndSettle(); + + expect(find.byType(PantallaTutorialAyuda), findsNothing); + expect(find.text('home stand-in'), findsOneWidget); + }, + ); + + testWidgets('Siguiente advances from the first page to the second', ( + tester, + ) async { + await tester.pumpWidget(_app(primerArranque: true)); + await tester.pump(); + + expect(find.text(l10n.tutorialPage1Headline), findsOneWidget); + + await tester.tap(find.text(l10n.tutorialNextAction)); + await tester.pumpAndSettle(); + + expect(find.text(l10n.tutorialPage2Headline), findsOneWidget); + }); + + testWidgets('Saltar is not offered on the last page', (tester) async { + await tester.pumpWidget(_app(primerArranque: true)); + await tester.pump(); + + final pageView = tester.widget(find.byType(PageView)); + pageView.controller!.jumpToPage(8); + await tester.pump(); + + expect(find.text(l10n.tutorialSkipAction), findsNothing); + }); + + testWidgets( + 'last page CTA reads "Empezar a escuchar" when reached via first launch', + (tester) async { + await tester.pumpWidget(_app(primerArranque: true)); + await tester.pump(); + + final pageView = tester.widget(find.byType(PageView)); + pageView.controller!.jumpToPage(8); + await tester.pump(); + + expect(find.text(l10n.welcomeCtaLabel), findsOneWidget); + expect(find.text(l10n.closeAction), findsNothing); + }, + ); + + testWidgets( + 'last page CTA reads "Cerrar" when reached manually from Ajustes', + (tester) async { + await tester.pumpWidget(_app(primerArranque: false)); + await tester.pump(); + + final pageView = tester.widget(find.byType(PageView)); + pageView.controller!.jumpToPage(8); + await tester.pump(); + + expect(find.text(l10n.closeAction), findsOneWidget); + expect(find.text(l10n.welcomeCtaLabel), findsNothing); + }, + ); + + testWidgets('tapping the last page CTA pops the route', (tester) async { + final navigatorKey = GlobalKey(); + await tester.pumpWidget( + MaterialApp( + navigatorKey: navigatorKey, + locale: const Locale('es'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: const Scaffold(body: Center(child: Text('home stand-in'))), + ), + ); + + unawaited( + navigatorKey.currentState!.push( + MaterialPageRoute( + builder: (_) => const PantallaTutorialAyuda(primerArranque: false), + ), + ), + ); + await tester.pumpAndSettle(); + + final pageView = tester.widget(find.byType(PageView)); + pageView.controller!.jumpToPage(8); + await tester.pump(); + + await tester.tap(find.text(l10n.closeAction)); + await tester.pumpAndSettle(); + + expect(find.byType(PantallaTutorialAyuda), findsNothing); + expect(find.text('home stand-in'), findsOneWidget); + }); + + testWidgets('the last page shows the "watch it again" reminder banner', ( + tester, + ) async { + await tester.pumpWidget(_app(primerArranque: true)); + await tester.pump(); + + final pageView = tester.widget(find.byType(PageView)); + pageView.controller!.jumpToPage(8); + await tester.pump(); + + expect(find.text(l10n.tutorialPage9BannerBody), findsOneWidget); + }); +} diff --git a/test/servicios/servicio_tutorial_ayuda_test.dart b/test/servicios/servicio_tutorial_ayuda_test.dart new file mode 100644 index 0000000..549dc09 --- /dev/null +++ b/test/servicios/servicio_tutorial_ayuda_test.dart @@ -0,0 +1,54 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:pluriwave/servicios/servicio_tutorial_ayuda.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +/// `ServicioTutorialAyuda` decides whether the 9-screen help/tutorial +/// carousel (`PantallaTutorialAyuda`) is still due on this launch. Same +/// injectable-prefs, versioned-key convention as `ServicioBienvenida`: a +/// plain one-time boolean flag, since this tutorial shows once (to both +/// fresh installs and existing installs upgrading to this version) and is +/// otherwise only reachable manually from Ajustes. +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('ServicioTutorialAyuda', () { + test( + 'debeMostrarTutorial is true before it has ever been marked seen', + () async { + SharedPreferences.setMockInitialValues({}); + final servicio = ServicioTutorialAyuda(); + + expect(await servicio.debeMostrarTutorial(), isTrue); + }, + ); + + test('debeMostrarTutorial is false after marcarTutorialVisto', () async { + SharedPreferences.setMockInitialValues({}); + final servicio = ServicioTutorialAyuda(); + + await servicio.marcarTutorialVisto(); + + expect(await servicio.debeMostrarTutorial(), isFalse); + }); + + test('respects a seen flag already persisted by a prior launch', () async { + SharedPreferences.setMockInitialValues({'pluri_tutorial_visto_v1': true}); + final servicio = ServicioTutorialAyuda(); + + expect(await servicio.debeMostrarTutorial(), isFalse); + }); + + test( + 'is still due on an existing install that has other unrelated flags ' + 'set but never this one (e.g. the welcome screen already seen)', + () async { + SharedPreferences.setMockInitialValues({ + 'pluri_bienvenida_vista_v1': true, + }); + final servicio = ServicioTutorialAyuda(); + + expect(await servicio.debeMostrarTutorial(), isTrue); + }, + ); + }); +}