diff --git a/lang/de.json b/lang/de.json index a68bed5a8c..04e2ca0b25 100644 --- a/lang/de.json +++ b/lang/de.json @@ -170,8 +170,69 @@ "No organizations found Please contact your admin": "Geen organisaties gevonden! Neem contact op met uw beheerder", "Notification Feature is not installed": "Meddelelsesfunktionen er ikke installeret", "For complete access, please": "Für vollständigen Zugriff bitte", - " join an organization.": " einer Organisation beitreten.", - "JOIN":"BEITRETEN", + "join an organization.": " einer Organisation beitreten.", + "JOIN": "BEITRETEN", "Camera": "Kamera", - "Gallery": "Galerie" + "Gallery": "Galerie", + "NEXT": "NÄCHSTE", + "COMPLETE": "VOLLSTÄNDIG", + "Start app tour to know talawa functioning": "Starten Sie die App-Tour, um die Funktionsweise von Talawa zu erfahren", + "Scan QR": "QR scannen", + "Add tag": "Tag hinzufügen", + "Enter the Tag": "Geben Sie das Tag ein", + "Title": "Titel", + "Choose on map": "Auf der Karte wählen", + "Where is the event?": "Wo ist das Ereignis?", + "Add Members": "Mitglieder hinzufügen", + "All Events": "Alle Veranstaltungen", + "Created Events": "Erstellte Veranstaltungen", + "Registered Events": "Registrierte Veranstaltungen", + "Send": "Senden", + "Write your comment here..": "Schreiben Sie hier Ihren Kommentar..", + "You need access": "Sie benötigen Zugang", + "Request access, or switch to an account with access": "Fordern Sie Zugang an oder wechseln Sie zu einem Konto mit Zugang", + "Request Access": "Zugang anfordern", + "Last Name": "Nachname", + "First Name": "Vorname", + "Edit Profile": "Profil bearbeiten", + "Log Out": "Ausloggen", + "Please Select an amount": "Bitte wählen Sie einen Betrag", + "Input custom amount": "Benutzerdefinierten Betrag eingeben", + "Organisation Name": "Name der Organisation", + "Choose an Organization": "Wählen Sie eine Organisation", + "Your Report has been sent to the Admin": "Ihr Bericht wurde an den Admin gesendet", + "Report the post to the Admin": "Melden Sie den Beitrag dem Admin", + "Do you really want to delete the post?": "Möchten Sie den Beitrag wirklich löschen?", + "Liked": "Gefällt", + "Add Task Title": "Aufgabentitel hinzufügen", + "Describe the task": "Beschreiben Sie die Aufgabe", + "Looks like there aren't any events.": "Es scheint keine Veranstaltungen zu geben.", + "You have not created any event.": "Sie haben keine Veranstaltung erstellt.", + "No registered events are present": "Keine registrierten Veranstaltungen vorhanden", + "There aren't any public events.": "Es gibt keine öffentlichen Veranstaltungen.", + "There aren't any private events.": "Es gibt keine privaten Veranstaltungen.", + "Donate to the Community": "An die Gemeinschaft spenden", + "Donating to": "Spenden an", + "Are you sure you want to delete this event?": "Sind Sie sicher, dass Sie diese Veranstaltung löschen möchten?", + "Are you sure you want to exit this organization?": "Sind Sie sicher, dass Sie diese Organisation verlassen möchten?", + "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc": "Dies ist der Profil-Tab, hier können Sie alle Optionen im Zusammenhang mit dem Konto, den App-Einstellungen, der Einladung, der Hilfe usw. sehen", + "You can edit application settings like language, theme etc from here": "Sie können die Einstellungen der Anwendung wie Sprache, Thema usw. von hier aus bearbeiten", + "For any help we are always there. You can reach us from here": "Für jede Hilfe sind wir immer da. Sie können uns von hier aus erreichen", + "Current selected Organization Name": "Name der aktuell ausgewählten Organisation", + "Click this button to see options related to switching, joining and leaving organization(s)": "Klicken Sie auf diese Schaltfläche, um Optionen zum Wechseln, Beitreten und Verlassen von Organisation(en) zu sehen", + "Current selected Organization's Name appears here": "Der Name der aktuell ausgewählten Organisation erscheint hier", + "All your joined organizations appear over here you can click on them to change the current organization": "Alle beigetretenen Organisationen erscheinen hier, Sie können darauf klicken, um die aktuelle Organisation zu wechseln", + "From this button you can join other listed organizations": "Über diese Schaltfläche können Sie anderen aufgeführten Organisationen beitreten", + "To leave the current organization you can use this option": "Um die aktuelle Organisation zu verlassen, können Sie diese Option nutzen", + "This is the post card you can like and comment on the post from the options available": "Dies ist die Postkarte, Sie können den Beitrag über die verfügbaren Optionen liken und kommentieren", + "This is the Events tab here you can see all event related information of the current selected organization": "Dies ist der Veranstaltungs-Tab, hier können Sie alle ereignisbezogenen Informationen der aktuell ausgewählten Organisation sehen", + "This is the home tab here you can see the latest post from other members of the current organization": "Dies ist der Home-Tab, hier können Sie den neuesten Beitrag von anderen Mitgliedern der aktuellen Organisation sehen", + "This section displays all the important post set by the organization admin(s)": "Dieser Abschnitt zeigt alle wichtigen Beiträge, die von den Admin(s) der Organisation festgelegt wurden", + "Filter Events based on categories": "Veranstaltungen nach Kategorien filtern", + "Filter Events between selected dates": "Veranstaltungen zwischen ausgewählten Daten filtern", + "Description of event to see more details click on the card": "Beschreibung der Veranstaltung, um weitere Details zu sehen, klicken Sie auf die Karte", + "This is the Create post tab here you can add post to the current selected organization": "Dies ist der Tab 'Beitrag erstellen', hier können Sie der aktuell ausgewählten Organisation einen Beitrag hinzufügen", + "This is the Chat tab here you can see all your messages of the current selected organization": "Dies ist der Chat-Tab, hier können Sie alle Ihre Nachrichten der aktuell ausgewählten Organisation sehen", + "To help your organization grow you can support them financially from here": "Um Ihre Organisation zu unterstützen, können Sie sie finanziell von hier aus unterstützen.", + "You are all set to go let's get you in": "Sie sind bereit zu gehen, lassen Sie uns Ihnen helfen." } diff --git a/lang/en.json b/lang/en.json index 2588cffeb7..bb3239fca6 100644 --- a/lang/en.json +++ b/lang/en.json @@ -169,8 +169,69 @@ "Dark Theme": "Dark Theme", "No organizations found Please contact your admin": "No organizations found ! Please contact your admin", "For complete access, please": "For complete access, please", - " join an organization.": " join an organization.", - "JOIN":"JOIN", + "join an organization.": " join an organization.", + "JOIN": "JOIN", "Camera": "Camera", - "Gallery": "Gallery" + "Gallery": "Gallery", + "NEXT": "NEXT", + "COMPLETE": "COMPLETE", + "Start app tour to know talawa functioning": "Start app tour to know talawa functioning", + "Scan QR": "Scan QR", + "Add tag": "Add tag", + "Enter the Tag": "Enter the Tag", + "Title": "Title", + "Choose on map": "Choose on map", + "Where is the event?": "Where is the event?", + "Add Members": "Add Members", + "All Events": "All Events", + "Created Events": "Created Events", + "Registered Events": "Registered Events", + "Send": "Send", + "Write your comment here..": "Write your comment here..", + "You need access": "You need access", + "Request access, or switch to an account with access": "Request access, or switch to an account with access", + "Request Access": "Request Access", + "Last Name": "Last Name", + "First Name": "First Name", + "Edit Profile": "Edit Profile", + "Log Out": "Log Out", + "Please Select an amount": "Please Select an amount", + "Input custom amount": "Input custom amount", + "Organisation Name": "Organisation Name", + "Choose an Organization": "Choose an Organization", + "Your Report has been sent to the Admin": "Your Report has been sent to the Admin", + "Report the post to the Admin": "Report the post to the Admin", + "Do you really want to delete the post?": "Do you really want to delete the post?", + "Liked": "Liked", + "Add Task Title": "Add Task Title", + "Describe the task": "Describe the task", + "Looks like there aren't any events.": "Looks like there aren't any events.", + "You have not created any event.": "You have not created any event.", + "No registered events are present": "No registered events are present", + "There aren't any public events.": "There aren't any public events.", + "There aren't any private events.": "There aren't any private events.", + "Donate to the Community": "Donate to the Community", + "Donating to": "Donating to", + "Are you sure you want to delete this event?": "Are you sure you want to delete this event?", + "Are you sure you want to exit this organization?": "Are you sure you want to exit this organization?", + "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc": "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc.", + "You can edit application settings like language, theme etc from here": "You can edit application settings like language, theme etc from here.", + "For any help we are always there. You can reach us from here": "For any help, we are always there. You can reach us from here.", + "Current selected Organization Name": "Current selected Organization Name", + "Click this button to see options related to switching, joining and leaving organization(s)": "Click this button to see options related to switching, joining and leaving organization(s).", + "Current selected Organization's Name appears here": "Current selected Organization's Name appears here.", + "All your joined organizations appear over here you can click on them to change the current organization": "All your joined organizations appear over here you can click on them to change the current organization.", + "From this button you can join other listed organizations": "From this button you can join other listed organizations.", + "To leave the current organization you can use this option": "To leave the current organization you can use this option.", + "This is the post card you can like and comment on the post from the options available": "This is the post card you can like and comment on the post from the options available.", + "This is the Events tab here you can see all event related information of the current selected organization": "This is the Events tab here you can see all event related information of the current selected organization.", + "This is the home tab here you can see the latest post from other members of the current organization": "This is the home tab here you can see the latest post from other members of the current organization.", + "This section displays all the important post set by the organization admin(s)": "This section displays all the important post set by the organization admin(s).", + "Filter Events based on categories": "Filter Events based on categories.", + "Filter Events between selected dates": "Filter Events between selected dates.", + "Description of event to see more details click on the card": "Description of event to see more details click on the card.", + "This is the Create post tab here you can add post to the current selected organization": "This is the Create post tab here you can add post to the current selected organization.", + "This is the Chat tab here you can see all your messages of the current selected organization": "This is the Chat tab here you can see all your messages of the current selected organization.", + "To help your organization grow you can support them financially from here": "To help your organization grow you can support them financially from here.", + "You are all set to go let's get you in": "You are all set to go let's get you in." } diff --git a/lang/es.json b/lang/es.json index 6c6e705f3a..b66ea3e211 100644 --- a/lang/es.json +++ b/lang/es.json @@ -67,7 +67,7 @@ "Where is the event": "Donde es el evento", "Add Location": "Añadir lugar", "Describe the event": "Describe el evento", - "Add Description": "Agregar descripción", + "Add Description": "Añadir descripción", "Add Event": "Añadir evento", "Add": "Agregarlo", "Add Image": "Añadir imagen", @@ -104,7 +104,7 @@ "My Events": "Mis Eventos", "Public Events": "Eventos publicos", "Private Events": "Eventos privados", - "Liked by": "Apreciado por", + "Liked by": "Gustado por", "Comments": "Comentarios", "FirstName LastName": "Nombre Apellido", "Pinned Posts": "Puestos fijadas", @@ -169,8 +169,69 @@ "Dismiss": "despedir", "No organizations found Please contact your admin": "Neniuj organizoj trovitaj! Bonvolu kontakti vian administranton", "For complete access, please": "Para acceso completo, por favor", - " join an organization.": " unirse a una organización.", - "JOIN":"UNIRSE", + "join an organization.": " unirse a una organización.", + "JOIN": "UNIRSE", "Camera": "Cámara", - "Gallery": "Galería" + "Gallery": "Galería", + "NEXT": "SIGUIENTE", + "COMPLETE": "COMPLETO", + "Start app tour to know talawa functioning": "Inicie el recorrido por la aplicación para conocer el funcionamiento de talawa", + "Scan QR": "Escanear QR", + "Add tag": "Añadir etiqueta", + "Enter the Tag": "Ingrese la Etiqueta", + "Title": "Título", + "Choose on map": "Elegir en el mapa", + "Where is the event?": "¿Dónde está el evento?", + "Add Members": "Añadir miembros", + "All Events": "Todos los eventos", + "Created Events": "Eventos creados", + "Registered Events": "Eventos registrados", + "Send": "Enviar", + "Write your comment here..": "Escribe tu comentario aquí..", + "You need access": "Necesitas acceso", + "Request access, or switch to an account with access": "Solicitar acceso o cambiar a una cuenta con acceso", + "Request Access": "Solicitar acceso", + "Last Name": "Apellido", + "First Name": "Nombre", + "Edit Profile": "Editar perfil", + "Log Out": "Cerrar sesión", + "Please Select an amount": "Por favor, seleccione una cantidad", + "Input custom amount": "Ingresar cantidad personalizada", + "Organisation Name": "Nombre de la organización", + "Choose an Organization": "Elija una Organización", + "Your Report has been sent to the Admin": "Su informe ha sido enviado al Administrador", + "Report the post to the Admin": "Reportar la publicación al Administrador", + "Do you really want to delete the post?": "¿Realmente quieres eliminar la publicación?", + "Liked": "Gustado", + "Add Task Title": "Añadir título de tarea", + "Describe the task": "Describir la tarea", + "Looks like there aren't any events.": "Parece que no hay eventos.", + "You have not created any event.": "No has creado ningún evento.", + "No registered events are present": "No hay eventos registrados", + "There aren't any public events.": "No hay eventos públicos.", + "There aren't any private events.": "No hay eventos privados.", + "Donate to the Community": "Donar a la Comunidad", + "Donating to": "Donando a", + "Are you sure you want to delete this event?": "¿Estás seguro de que quieres eliminar este evento?", + "Are you sure you want to exit this organization?": "¿Estás seguro de que quieres salir de esta organización?", + "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc": "Esta es la pestaña de Perfil, aquí puedes ver todas las opciones relacionadas con la cuenta, configuración de la aplicación, invitación, ayuda, etc.", + "You can edit application settings like language, theme etc from here": "Puedes editar la configuración de la aplicación, como el idioma, el tema, etc., desde aquí", + "For any help we are always there. You can reach us from here": "Para cualquier ayuda, siempre estamos aquí. Puedes contactarnos desde aquí", + "Current selected Organization Name": "Nombre de la organización actualmente seleccionada", + "Click this button to see options related to switching, joining and leaving organization(s)": "Haz clic en este botón para ver opciones relacionadas con cambiar, unirse y salir de organizaciones", + "Current selected Organization's Name appears here": "El nombre de la organización actualmente seleccionada aparece aquí", + "All your joined organizations appear over here you can click on them to change the current organization": "Todas las organizaciones a las que te has unido aparecen aquí; puedes hacer clic en ellas para cambiar la organización actual", + "From this button you can join other listed organizations": "Desde este botón, puedes unirte a otras organizaciones enumeradas", + "To leave the current organization you can use this option": "Para salir de la organización actual, puedes usar esta opción", + "This is the post card you can like and comment on the post from the options available": "Esta es la tarjeta de la publicación; puedes darle me gusta y comentar en la publicación desde las opciones disponibles", + "This is the Events tab here you can see all event related information of the current selected organization": "Esta es la pestaña de Eventos; aquí puedes ver toda la información relacionada con eventos de la organización actualmente seleccionada", + "This is the home tab here you can see the latest post from other members of the current organization": "Esta es la pestaña de Inicio; aquí puedes ver la última publicación de otros miembros de la organización actual", + "This section displays all the important post set by the organization admin(s)": "Esta sección muestra todas las publicaciones importantes establecidas por el(los) administrador(es) de la organización", + "Filter Events based on categories": "Filtrar eventos según categorías", + "Filter Events between selected dates": "Filtrar eventos entre las fechas seleccionadas", + "Description of event to see more details click on the card": "Descripción del evento; para ver más detalles, haz clic en la tarjeta", + "This is the Create post tab here you can add post to the current selected organization": "Esta es la pestaña de Crear publicación; aquí puedes agregar una publicación a la organización actualmente seleccionada", + "This is the Chat tab here you can see all your messages of the current selected organization": "Esta es la pestaña de Chat; aquí puedes ver todos tus mensajes de la organización actualmente seleccionada", + "To help your organization grow you can support them financially from here": "Para ayudar a que tu organización crezca, puedes apoyarla financieramente desde aquí", + "You are all set to go let's get you in": "Estás listo para ir, vamos a empezar" } diff --git a/lang/fr.json b/lang/fr.json index 3ed1ff2ab6..f15f4ec01e 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -169,8 +169,69 @@ "Dark Theme": "Thème sombre", "No organizations found Please contact your admin": "Aucune organisation trouvée ! Veuillez contacter votre administrateur", "For complete access, please": "Pour un accès complet, veuillez", - " join an organization.": " rejoindre une organisation.", - "JOIN":"REJOINDRE", + "join an organization.": " rejoindre une organisation.", + "JOIN": "REJOINDRE", "Camera": "Caméra", - "Gallery": "Galerie" + "Gallery": "Galerie", + "NEXT": "SUIVANT", + "COMPLETE": "COMPLÉTER", + "Start app tour to know talawa functioning": "Démarrez la visite de l'application pour connaître le fonctionnement de talawa", + "Scan QR": "Scanner QR", + "Add tag": "Ajouter un tag", + "Enter the Tag": "Entrez le Tag", + "Title": "Titre", + "Choose on map": "Choisir sur la carte", + "Where is the event?": "Où se trouve l'événement?", + "Add Members": "Ajouter des membres", + "All Events": "Tous les événements", + "Created Events": "Événements créés", + "Registered Events": "Événements enregistrés", + "Send": "Envoyer", + "Write your comment here..": "Écrivez votre commentaire ici..", + "You need access": "Vous avez besoin d'accès", + "Request access, or switch to an account with access": "Demander un accès ou passer à un compte avec accès", + "Request Access": "Demander l'accès", + "Last Name": "Nom de famille", + "First Name": "Prénom", + "Edit Profile": "Modifier le profil", + "Log Out": "Se déconnecter", + "Please Select an amount": "Veuillez sélectionner un montant", + "Input custom amount": "Entrer un montant personnalisé", + "Organisation Name": "Nom de l'organisation", + "Choose an Organization": "Choisissez une Organisation", + "Your Report has been sent to the Admin": "Votre rapport a été envoyé à l'Admin", + "Report the post to the Admin": "Signaler le post à l'Admin", + "Do you really want to delete the post?": "Voulez-vous vraiment supprimer le post?", + "Liked": "Aimé", + "Add Task Title": "Ajouter un titre de tâche", + "Describe the task": "Décrire la tâche", + "Looks like there aren't any events.": "On dirait qu'il n'y a pas d'événements.", + "You have not created any event.": "Vous n'avez créé aucun événement.", + "No registered events are present": "Aucun événement enregistré n'est présent", + "There aren't any public events.": "Il n'y a pas d'événements publics.", + "There aren't any private events.": "Il n'y a pas d'événements privés.", + "Donate to the Community": "Faire un don à la Communauté", + "Donating to": "Don à", + "Are you sure you want to delete this event?": "Êtes-vous sûr de vouloir supprimer cet événement?", + "Are you sure you want to exit this organization?": "Êtes-vous sûr de vouloir quitter cette organisation?", + "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc": "Ceci est l'onglet Profil où vous pouvez voir toutes les options liées au compte, aux paramètres de l'application, à l'invitation, à l'aide, etc.", + "You can edit application settings like language, theme etc from here": "Vous pouvez modifier les paramètres de l'application comme la langue, le thème, etc. depuis ici", + "For any help we are always there. You can reach us from here": "Pour toute aide, nous sommes toujours là. Vous pouvez nous joindre depuis ici", + "Current selected Organization Name": "Nom de l'organisation actuellement sélectionnée", + "Click this button to see options related to switching, joining and leaving organization(s)": "Cliquez sur ce bouton pour voir les options liées au changement, à l'adhésion et au départ d'organisation(s)", + "Current selected Organization's Name appears here": "Le nom de l'organisation actuellement sélectionnée apparaît ici", + "All your joined organizations appear over here you can click on them to change the current organization": "Toutes les organisations auxquelles vous avez adhéré apparaissent ici, vous pouvez cliquer sur elles pour changer l'organisation actuelle", + "From this button you can join other listed organizations": "À partir de ce bouton, vous pouvez rejoindre d'autres organisations répertoriées", + "To leave the current organization you can use this option": "Pour quitter l'organisation actuelle, vous pouvez utiliser cette option", + "This is the post card you can like and comment on the post from the options available": "Ceci est la carte de publication, vous pouvez aimer et commenter la publication à partir des options disponibles", + "This is the Events tab here you can see all event related information of the current selected organization": "Ceci est l'onglet Événements, ici vous pouvez voir toutes les informations liées aux événements de l'organisation actuellement sélectionnée", + "This is the home tab here you can see the latest post from other members of the current organization": "Ceci est l'onglet Accueil, ici vous pouvez voir le dernier post des autres membres de l'organisation actuelle", + "This section displays all the important post set by the organization admin(s)": "Cette section affiche tous les posts importants définis par le(s) administrateur(s) de l'organisation", + "Filter Events based on categories": "Filtrer les événements en fonction des catégories", + "Filter Events between selected dates": "Filtrer les événements entre les dates sélectionnées", + "Description of event to see more details click on the card": "Description de l'événement, pour voir plus de détails, cliquez sur la carte", + "This is the Create post tab here you can add post to the current selected organization": "Ceci est l'onglet Créer une publication, ici vous pouvez ajouter une publication à l'organisation actuellement sélectionnée", + "This is the Chat tab here you can see all your messages of the current selected organization": "Ceci est l'onglet Chat, ici vous pouvez voir tous vos messages de l'organisation actuellement sélectionnée", + "To help your organization grow you can support them financially from here": "Pour aider votre organisation à se développer, vous pouvez les soutenir financièrement depuis ici.", + "You are all set to go let's get you in": "Vous êtes prêt à partir, laissez-nous vous aider." } diff --git a/lang/hi.json b/lang/hi.json index 8ae54f08e5..6a556ce4de 100644 --- a/lang/hi.json +++ b/lang/hi.json @@ -169,8 +169,69 @@ "Dismiss": "नकार", "No organizations found Please contact your admin": "कोई संगठन नहीं मिला! कृपया अपने व्यवस्थापक से संपर्क करें", "For complete access, please": "पूर्ण पहुंच के लिए, कृपया", - " join an organization.": " किसी संगठन से जुड़ें.", - "JOIN":"जोड़ना", + "join an organization.": " किसी संगठन से जुड़ें.", + "JOIN": "जोड़ना", "Camera": "कैमरा", - "Gallery": "गैलरी" + "Gallery": "गैलरी", + "NEXT": "अगला", + "COMPLETE": "पूर्ण", + "Start app tour to know talawa functioning": "Talawa कार्यप्रणाली जानने के लिए ऐप टूर शुरू करें", + "Scan QR": "QR स्कैन करें", + "Add tag": "टैग जोड़ें", + "Enter the Tag": "टैग दर्ज करें", + "Title": "शीर्षक", + "Choose on map": "नक्शे पर चुनें", + "Where is the event?": "इवेंट कहाँ है?", + "Add Members": "सदस्य जोड़ें", + "All Events": "सभी ईवेंट्स", + "Created Events": "बनाए गए ईवेंट्स", + "Registered Events": "पंजीकृत ईवेंट्स", + "Send": "भेजें", + "Write your comment here..": "यहां अपनी टिप्पणी लिखें..", + "You need access": "आपको पहुँच की आवश्यकता है", + "Request access, or switch to an account with access": "पहुँच का अनुरोध करें, या पहुँच वाले खाते में स्विच करें", + "Request Access": "पहुँच का अनुरोध करें", + "Last Name": "अंतिम नाम", + "First Name": "पहला नाम", + "Edit Profile": "प्रोफ़ाइल संपादित करें", + "Log Out": "लॉग आउट", + "Please Select an amount": "कृपया एक राशि चुनें", + "Input custom amount": "कस्टम राशि दर्ज करें", + "Organisation Name": "संगठन का नाम", + "Choose an Organization": "एक संगठन चुनें", + "Your Report has been sent to the Admin": "आपकी रिपोर्ट एडमिन को भेज दी गई है", + "Report the post to the Admin": "पोस्ट को एडमिन को रिपोर्ट करें", + "Do you really want to delete the post?": "क्या आप वाकई पोस्ट को हटाना चाहते हैं?", + "Liked": "पसंद किया", + "Add Task Title": "टास्क का शीर्षक जोड़ें", + "Describe the task": "कार्य का वर्णन करें", + "Looks like there aren't any events.": "लगता है कि कोई इवेंट नहीं हैं।", + "You have not created any event.": "आपने कोई इवेंट नहीं बनाया है।", + "No registered events are present": "कोई पंजीकृत इवेंट मौजूद नहीं हैं", + "There aren't any public events.": "कोई सार्वजनिक इवेंट नहीं हैं।", + "There aren't any private events.": "कोई निजी इवेंट नहीं हैं।", + "Donate to the Community": "समुदाय को दान करें", + "Donating to": "को दान देना", + "Are you sure you want to delete this event?": "क्या आप वाकई इस इवेंट को हटाना चाहते हैं?", + "Are you sure you want to exit this organization?": "क्या आप वाकई इस संगठन से बाहर जाना चाहते हैं?", + "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc": "यह प्रोफाइल टैब है जहाँ आप खाता, ऐप सेटिंग, आमंत्रण, सहायता आदि से संबंधित सभी विकल्प देख सकते हैं", + "You can edit application settings like language, theme etc from here": "आप यहाँ से भाषा, थीम आदि जैसी एप्लिकेशन सेटिंग्स को संपादित कर सकते हैं", + "For any help we are always there. You can reach us from here": "किसी भी मदद के लिए हम हमेशा यहाँ होते हैं। आप हमसे यहाँ संपर्क कर सकते हैं", + "Current selected Organization Name": "वर्तमान चयनित संगठन का नाम", + "Click this button to see options related to switching, joining and leaving organization(s)": "स्विचिंग, ज्वाइनिंग और ऑर्गनाइजेशन छोड़ने से संबंधित विकल्प देखने के लिए इस बटन पर क्लिक करें।", + "Current selected Organization's Name appears here": "वर्तमान चयनित संगठन का नाम यहाँ दिखाई देता है।", + "All your joined organizations appear over here you can click on them to change the current organization": "यहाँ सभी आपके जुड़े हुए संगठन दिखाई देते हैं, आप इन पर क्लिक करके वर्तमान संगठन को बदल सकते हैं।", + "From this button you can join other listed organizations": "इस बटन से आप अन्य सूचीबद्ध संगठनों में शामिल हो सकते हैं।", + "To leave the current organization you can use this option": "वर्तमान संगठन छोड़ने के लिए आप इस विकल्प का उपयोग कर सकते हैं।", + "This is the post card you can like and comment on the post from the options available": "यह वह पोस्ट कार्ड है जिस पर आप उपलब्ध विकल्पों से पसंद और टिप्पणी कर सकते हैं।", + "This is the Events tab here you can see all event related information of the current selected organization": "यहाँ इवेंट्स टैब है जहाँ आप वर्तमान चयनित संगठन की सभी इवेंट संबंधित जानकारी देख सकते हैं।", + "This is the home tab here you can see the latest post from other members of the current organization": "यहाँ होम टैब है जहाँ आप वर्तमान संगठन के अन्य सदस्यों के नवीनतम पोस्ट देख सकते हैं।", + "This section displays all the important post set by the organization admin(s)": "यह खंड वह सभी महत्वपूर्ण पोस्ट दिखाता है जो संगठन एडमिन द्वारा निर्धारित की गई हैं।", + "Filter Events based on categories": "श्रेणियों के आधार पर इवेंट्स को फ़िल्टर करें।", + "Filter Events between selected dates": "चयनित तिथियों के बीच इवेंट्स को फ़िल्टर करें।", + "Description of event to see more details click on the card": "इवेंट का विवरण और विवरण देखने के लिए कार्ड पर क्लिक करें।", + "This is the Create post tab here you can add post to the current selected organization": "यह यहाँ से तैयार करें पोस्ट टैब है जहाँ आप वर्तमान चयनित संगठन में पोस्ट जोड़ सकते हैं।", + "This is the Chat tab here you can see all your messages of the current selected organization": "यहाँ चैट टैब है जहाँ आप वर्तमान चयनित संगठन के सभी संदेश देख सकते हैं।", + "To help your organization grow you can support them financially from here": "अपने संगठन को बढ़ावा देने के लिए आप उन्हें यहाँ से वित्तपोषण दे सकते हैं।", + "You are all set to go let's get you in": "आप तैयार हैं जाने के लिए, चलो आपको एंटर करते हैं।" } diff --git a/lang/ja.json b/lang/ja.json index 6a57e49f7c..ac8f5c1b73 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -104,7 +104,7 @@ "My Events": "私のイベント", "Public Events": "公開イベント", "Private Events": "プライベートイベント", - "Liked by": "好きな人", + "Liked by": "によって好まれる", "Comments": "コメント", "FirstName LastName": "名前苗字", "Pinned Posts": "固定された投稿", @@ -169,8 +169,69 @@ "Dismiss": "解散", "No organizations found Please contact your admin": "組織が見つかりません!管理者に連絡してください", "For complete access, please": "完全にアクセスするには、", - " join an organization.": " 組織に参加します。", + "join an organization.": " 組織に参加します。", "JOIN": "参加する", "Camera": "カメラ", - "Gallery": "ギャラリー" + "Gallery": "ギャラリー", + "NEXT": "次へ", + "COMPLETE": "完了", + "Start app tour to know talawa functioning": "タラワの機能を知るためにアプリツアーを開始する", + "Scan QR": "QRをスキャン", + "Add tag": "タグを追加する", + "Enter the Tag": "タグを入力してください", + "Title": "タイトル", + "Choose on map": "地図上で選択する", + "Where is the event?": "イベントはどこですか?", + "Add Members": "メンバーを追加する", + "All Events": "すべてのイベント", + "Created Events": "作成されたイベント", + "Registered Events": "登録されたイベント", + "Send": "送信", + "Write your comment here..": "ここにコメントを書いてください..", + "You need access": "アクセスが必要です", + "Request access, or switch to an account with access": "アクセスを要求するか、アクセス権のあるアカウントに切り替える", + "Request Access": "アクセスをリクエストする", + "Last Name": "苗字", + "First Name": "名", + "Edit Profile": "プロフィールを編集", + "Log Out": "ログアウト", + "Please Select an amount": "金額を選択してください", + "Input custom amount": "カスタム金額を入力", + "Organisation Name": "組織の名前", + "Choose an Organization": "組織を選択する", + "Your Report has been sent to the Admin": "あなたのレポートは管理者に送信されました", + "Report the post to the Admin": "投稿を管理者に報告する", + "Do you really want to delete the post?": "本当に投稿を削除しますか?", + "Liked": "いいね", + "Add Task Title": "タスクのタイトルを追加", + "Describe the task": "タスクを説明する", + "Looks like there aren't any events.": "イベントがないようです。", + "You have not created any event.": "あなたはどんなイベントも作成していません。", + "No registered events are present": "登録されたイベントは存在しません", + "There aren't any public events.": "公開イベントはありません。", + "There aren't any private events.": "プライベートイベントはありません。", + "Donate to the Community": "コミュニティに寄付する", + "Donating to": "に寄付する", + "Are you sure you want to delete this event?": "このイベントを削除してもよろしいですか?", + "Are you sure you want to exit this organization?": "この組織を退出してもよろしいですか?", + "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc": "これはプロファイルタブです。ここでは、アカウント、アプリの設定、招待、ヘルプなどに関連するすべてのオプションを見ることができます。", + "You can edit application settings like language, theme etc from here": "ここから言語、テーマなどのアプリケーションの設定を編集できます。", + "For any help we are always there. You can reach us from here": "お手伝いが必要な場合はいつでもお手伝いします。ここからお問い合わせいただけます。", + "Current selected Organization Name": "現在選択されている組織の名前", + "Click this button to see options related to switching, joining and leaving organization(s)": "組織の切り替え、参加、退出に関連するオプションを見るには、このボタンをクリックしてください。", + "Current selected Organization's Name appears here": "現在選択されている組織の名前がここに表示されます。", + "All your joined organizations appear over here you can click on them to change the current organization": "参加したすべての組織がここに表示され、現在の組織を変更するにはそれらをクリックできます。", + "From this button you can join other listed organizations": "このボタンから他のリストされた組織に参加できます。", + "To leave the current organization you can use this option": "現在の組織を退出するには、このオプションを使用できます。", + "This is the post card you can like and comment on the post from the options available": "これは投稿カードです。利用可能なオプションから投稿にいいねやコメントをすることができます。", + "This is the Events tab here you can see all event related information of the current selected organization": "これはイベントタブです。ここでは、現在選択されている組織の関連するすべてのイベント情報を見ることができます。", + "This is the home tab here you can see the latest post from other members of the current organization": "これはホームタブです。ここでは、現在の組織の他のメンバーの最新の投稿を見ることができます。", + "This section displays all the important post set by the organization admin(s)": "このセクションには組織の管理者によって設定されたすべての重要な投稿が表示されます。", + "Filter Events based on categories": "カテゴリに基づいてイベントをフィルタリング", + "Filter Events between selected dates": "選択した日付の間でイベントをフィルタリング", + "Description of event to see more details click on the card": "詳細を見るには、イベントの説明をクリックしてください。", + "This is the Create post tab here you can add post to the current selected organization": "これは投稿を作成するタブです。ここでは、現在選択されている組織に投稿を追加できます。", + "This is the Chat tab here you can see all your messages of the current selected organization": "これはチャットタブです。ここでは、現在選択されている組織のすべてのメッセージを見ることができます。", + "To help your organization grow you can support them financially from here": "組織の成長をサポートするためには、ここから経済的にサポートできます。", + "You are all set to go let's get you in": "準備が整いました。さあ、始めましょう。" } diff --git a/lang/pt.json b/lang/pt.json index 1b156b3b68..1b2c338c2b 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -104,7 +104,7 @@ "My Events": "Meus Eventos", "Public Events": "Eventos Públicos", "Private Events": "Eventos Privados", - "Liked by": "Apreciado por", + "Liked by": "Curtido por", "Comments": "Comentários", "FirstName LastName": "Primeiro nome, ultimo nome", "Pinned Posts": "Postagens fixadas", @@ -169,8 +169,69 @@ "Dismiss": "liberar", "No organizations found Please contact your admin": "Neniuj organizoj trovitaj! Bonvolu kontakti vian administranton", "For complete access, please": "Para acesso completo, por favor", - " join an organization.": " ingressar em uma organização.", - "JOIN":"ENTRAR", + "join an organization.": " ingressar em uma organização.", + "JOIN": "ENTRAR", "Camera": "Câmera", - "Gallery": "Galeria" + "Gallery": "Galeria", + "NEXT": "PRÓXIMO", + "COMPLETE": "COMPLETO", + "Start app tour to know talawa functioning": "Inicie o tour do aplicativo para conhecer o funcionamento do talawa", + "Scan QR": "Escanear QR", + "Add tag": "Adicionar tag", + "Enter the Tag": "Digite a Tag", + "Title": "Título", + "Choose on map": "Escolher no mapa", + "Where is the event?": "Onde é o evento?", + "Add Members": "Adicionar membros", + "All Events": "Todos os eventos", + "Created Events": "Eventos criados", + "Registered Events": "Eventos registrados", + "Send": "Enviar", + "Write your comment here..": "Escreva seu comentário aqui..", + "You need access": "Você precisa de acesso", + "Request access, or switch to an account with access": "Solicitar acesso ou mudar para uma conta com acesso", + "Request Access": "Solicitar acesso", + "Last Name": "Sobrenome", + "First Name": "Nome", + "Edit Profile": "Editar perfil", + "Log Out": "Sair", + "Please Select an amount": "Por favor, selecione um valor", + "Input custom amount": "Inserir valor personalizado", + "Organisation Name": "Nome da Organização", + "Choose an Organization": "Escolha uma Organização", + "Your Report has been sent to the Admin": "Seu relatório foi enviado ao Administrador", + "Report the post to the Admin": "Reportar a postagem ao Administrador", + "Do you really want to delete the post?": "Você realmente quer deletar a postagem?", + "Liked": "Curtido", + "Add Task Title": "Adicionar título da tarefa", + "Describe the task": "Descrever a tarefa", + "Looks like there aren't any events.": "Parece que não há eventos.", + "You have not created any event.": "Você não criou nenhum evento.", + "No registered events are present": "Não há eventos registrados", + "There aren't any public events.": "Não há eventos públicos.", + "There aren't any private events.": "Não há eventos privados.", + "Donate to the Community": "Doar para a Comunidade", + "Donating to": "Doando para", + "Are you sure you want to delete this event?": "Tem certeza de que deseja excluir este evento?", + "Are you sure you want to exit this organization?": "Tem certeza de que deseja sair desta organização?", + "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc": "Esta é a aba de Perfil, onde você pode ver todas as opções relacionadas à conta, configurações do aplicativo, convites, ajuda, etc.", + "You can edit application settings like language, theme etc from here": "Você pode editar as configurações do aplicativo, como idioma, tema, etc., a partir daqui", + "For any help we are always there. You can reach us from here": "Para qualquer ajuda, estamos sempre aqui. Você pode nos contatar a partir daqui", + "Current selected Organization Name": "Nome da organização atualmente selecionada", + "Click this button to see options related to switching, joining and leaving organization(s)": "Clique neste botão para ver opções relacionadas a trocar, juntar-se e sair de organizações", + "Current selected Organization's Name appears here": "O nome da organização atualmente selecionada aparece aqui", + "All your joined organizations appear over here you can click on them to change the current organization": "Todas as organizações às quais você se juntou aparecem aqui; você pode clicar nelas para mudar a organização atual", + "From this button you can join other listed organizations": "A partir deste botão, você pode se juntar a outras organizações listadas", + "To leave the current organization you can use this option": "Para sair da organização atual, você pode usar esta opção", + "This is the post card you can like and comment on the post from the options available": "Este é o cartão de postagem; você pode curtir e comentar na postagem a partir das opções disponíveis", + "This is the Events tab here you can see all event related information of the current selected organization": "Esta é a aba de Eventos; aqui você pode ver todas as informações relacionadas a eventos da organização atualmente selecionada", + "This is the home tab here you can see the latest post from other members of the current organization": "Esta é a aba Início; aqui você pode ver a última postagem de outros membros da organização atual", + "This section displays all the important post set by the organization admin(s)": "Esta seção exibe todas as postagens importantes definidas pelos administradores da organização", + "Filter Events based on categories": "Filtre eventos com base em categorias", + "Filter Events between selected dates": "Filtre eventos entre as datas selecionadas", + "Description of event to see more details click on the card": "Descrição do evento; para ver mais detalhes, clique no cartão", + "This is the Create post tab here you can add post to the current selected organization": "Esta é a aba de Criar postagem; aqui você pode adicionar uma postagem à organização atualmente selecionada", + "This is the Chat tab here you can see all your messages of the current selected organization": "Esta é a aba de Chat; aqui você pode ver todas as suas mensagens da organização atualmente selecionada", + "To help your organization grow you can support them financially from here": "Para ajudar sua organização a crescer, você pode apoiá-la financeiramente a partir daqui", + "You are all set to go let's get you in": "Você está pronto para ir; vamos começar" } diff --git a/lang/zh.json b/lang/zh.json index 42d7157e05..8c7f25b69a 100644 --- a/lang/zh.json +++ b/lang/zh.json @@ -67,7 +67,7 @@ "Where is the event": "活动地点", "Add Location": "添加位置", "Describe the event": "描述事件", - "Add Description": "添加说明", + "Add Description": "添加描述", "Add Event": "添加事件", "Add": "添加", "Add Image": "添加图片", @@ -169,8 +169,69 @@ "Dismiss": "解雇", "No organizations found Please contact your admin": "Neniuj organizoj trovitaj! Bonvolu kontakti vian administranton", "For complete access, please": "如需完整访问,请", - " join an organization.": " 加入一个组织。", - "JOIN":"加入", + "join an organization.": " 加入一个组织。", + "JOIN": "加入", "Camera": "相机", - "Gallery": "画廊" + "Gallery": "画廊", + "NEXT": "下一个", + "COMPLETE": "完成", + "Start app tour to know talawa functioning": "启动应用程序导览以了解塔拉瓦的功能", + "Scan QR": "扫描QR码", + "Add tag": "添加标签", + "Enter the Tag": "输入标签", + "Title": "标题", + "Choose on map": "在地图上选择", + "Where is the event?": "事件在哪里?", + "Add Members": "添加成员", + "All Events": "所有活动", + "Created Events": "创建的活动", + "Registered Events": "注册的活动", + "Send": "发送", + "Write your comment here..": "在此处写下您的评论..", + "You need access": "您需要访问权限", + "Request access, or switch to an account with access": "请求访问权限,或切换到有访问权限的账户", + "Request Access": "请求访问", + "Last Name": "姓氏", + "First Name": "名字", + "Edit Profile": "编辑个人资料", + "Log Out": "登出", + "Please Select an amount": "请选择一个金额", + "Input custom amount": "输入自定义金额", + "Organisation Name": "组织名称", + "Choose an Organization": "选择一个组织", + "Your Report has been sent to the Admin": "您的报告已发送给管理员", + "Report the post to the Admin": "向管理员举报帖子", + "Do you really want to delete the post?": "您真的想要删除这个帖子吗?", + "Liked": "喜欢", + "Add Task Title": "添加任务标题", + "Describe the task": "描述任务", + "Looks like there aren't any events.": "看起来没有任何活动。", + "You have not created any event.": "您还没有创建任何活动。", + "No registered events are present": "没有注册的活动", + "There aren't any public events.": "没有公开的活动。", + "There aren't any private events.": "没有私人活动。", + "Donate to the Community": "向社区捐款", + "Donating to": "捐赠给", + "Are you sure you want to delete this event?": "您确定要删除此活动吗?", + "Are you sure you want to exit this organization?": "您确定要退出这个组织吗?", + "This is the Profile tab here you can see all options related to account, app setting, invitation, help etc": "这是个人资料选项卡,您可以在此处查看与帐户、应用设置、邀请、帮助等相关的所有选项。", + "You can edit application settings like language, theme etc from here": "您可以从这里编辑应用程序设置,如语言、主题等。", + "For any help we are always there. You can reach us from here": "任何帮助我们都会在这里。您可以通过这里联系我们。", + "Current selected Organization Name": "当前选择的组织名称", + "Click this button to see options related to switching, joining and leaving organization(s)": "单击此按钮以查看与切换、加入和离开组织相关的选项。", + "Current selected Organization's Name appears here": "当前选择的组织名称将显示在此处。", + "All your joined organizations appear over here you can click on them to change the current organization": "您加入的所有组织都会显示在这里,您可以单击它们以更改当前的组织。", + "From this button you can join other listed organizations": "您可以通过此按钮加入其他列出的组织。", + "To leave the current organization you can use this option": "要离开当前组织,您可以使用此选项。", + "This is the post card you can like and comment on the post from the options available": "这是帖子卡片,您可以从可用的选项中点赞并评论帖子。", + "This is the Events tab here you can see all event related information of the current selected organization": "这是活动选项卡,您可以在此处查看当前选择组织的所有与活动相关的信息。", + "This is the home tab here you can see the latest post from other members of the current organization": "这是主页选项卡,您可以在此处查看当前组织其他成员的最新帖子。", + "This section displays all the important post set by the organization admin(s)": "此部分显示由组织管理员设置的所有重要帖子。", + "Filter Events based on categories": "基于类别筛选事件", + "Filter Events between selected dates": "在选定的日期之间筛选事件", + "Description of event to see more details click on the card": "事件描述以查看更多详情,请单击卡片。", + "This is the Create post tab here you can add post to the current selected organization": "这是创建帖子选项卡,您可以在此处向当前选择的组织添加帖子。", + "This is the Chat tab here you can see all your messages of the current selected organization": "这是聊天选项卡,您可以在此处查看当前选择组织的所有消息。", + "To help your organization grow you can support them financially from here": "要帮助您的组织成长,您可以从这里提供财务支持。", + "You are all set to go let's get you in": "您已经准备好了,让我们开始吧。" } diff --git a/lib/main.dart b/lib/main.dart index 7ec3b18905..4ed80df749 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -252,6 +252,7 @@ class _MyAppState extends State { AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, ], title: 'Talawa', theme: Provider.of(context).isdarkTheme diff --git a/lib/services/navigation_service.dart b/lib/services/navigation_service.dart index 805bcc7680..909a91a2d8 100644 --- a/lib/services/navigation_service.dart +++ b/lib/services/navigation_service.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:talawa/enums/enums.dart'; +import 'package:talawa/utils/app_localization.dart'; import 'package:talawa/widgets/talawa_error_dialog.dart'; import 'package:talawa/widgets/talawa_error_snackbar.dart'; @@ -122,7 +123,10 @@ class NavigationService { SnackBar( behavior: SnackBarBehavior.floating, duration: duration, - content: Text(message), + content: Text( + AppLocalizations.of(navigatorKey.currentContext!)! + .strictTranslate(message), + ), ), ); } diff --git a/lib/view_model/main_screen_view_model.dart b/lib/view_model/main_screen_view_model.dart index 9766c29f5c..6aa06ee37a 100644 --- a/lib/view_model/main_screen_view_model.dart +++ b/lib/view_model/main_screen_view_model.dart @@ -1,749 +1,749 @@ -import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:hive/hive.dart'; -import 'package:talawa/locator.dart'; -import 'package:talawa/models/app_tour.dart'; -import 'package:talawa/plugins/fetch_plugin_list.dart'; -import 'package:talawa/utils/app_localization.dart'; -import 'package:talawa/view_model/base_view_model.dart'; -// import 'package:talawa/views/after_auth_screens/chat/chat_list_screen.dart'; -import 'package:talawa/views/after_auth_screens/events/explore_events.dart'; -import 'package:talawa/views/after_auth_screens/feed/organization_feed.dart'; -import 'package:talawa/views/after_auth_screens/profile/profile_page.dart'; -import 'package:talawa/views/demo_screens/explore_events_demo.dart'; -import 'package:talawa/views/demo_screens/organization_feed_demo.dart'; -import 'package:talawa/views/demo_screens/profile_page_demo.dart'; -import 'package:talawa/widgets/custom_alert_dialog.dart'; -import 'package:talawa/widgets/theme_switch.dart'; -import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; - -/// MainScreenViewModel class provide methods to interact with the modal to serve data in user's action in Main Screen Views. -/// -/// The functions in this class are -/// mainly in the context of Tutorials for different componenets of the App. -/// -/// Functions include: -/// * `showTutorial` -/// * `showHome` -/// * `tourEventTargets` -/// * `tourAddPost` -/// * `tourChat` -/// * `tourProfile` -class MainScreenViewModel extends BaseModel { - /// static variables. - static final GlobalKey scaffoldKey = - GlobalKey(); - - /// static variables. - final GlobalKey keyBNHome = GlobalKey(debugLabel: "HomeTab"); - - /// static variables. - final GlobalKey keyBNDemoHome = GlobalKey(debugLabel: "DemoHomeTab"); - - /// static variables. - final GlobalKey keySHPinnedPost = - GlobalKey(debugLabel: "HomeScreenPinnedPost"); - - /// static variables. - final GlobalKey keySHPost = GlobalKey(debugLabel: "HomeScreenPost"); - - /// static variables. - final GlobalKey keySHOrgName = GlobalKey(debugLabel: "HomeScreenOrgName"); - - /// static variables. - final GlobalKey keySHMenuIcon = GlobalKey(debugLabel: "HomeScreenMenuIcon"); - - /// static variables. - static final GlobalKey keyDrawerCurOrg = - GlobalKey(debugLabel: "DrawerCurrentOrg"); - - /// static variables. - static final GlobalKey keyDrawerSwitchableOrg = - GlobalKey(debugLabel: "DrawerSwitchableOrg"); - - /// static variables. - static final GlobalKey keyDrawerJoinOrg = - GlobalKey(debugLabel: "DrawerJoinOrg"); - - /// static variables. - static final GlobalKey keyDrawerLeaveCurrentOrg = - GlobalKey(debugLabel: "DrawerLeaveCurrentOr"); - - /// static variables. - final GlobalKey keyBNEvents = GlobalKey(debugLabel: "EventTab"); - - /// static variables. - final GlobalKey keyBNDemoEvents = GlobalKey(debugLabel: "DemoEventTab"); - - /// static variables. - final GlobalKey keySECategoryMenu = - GlobalKey(debugLabel: "EventScreenCategory"); - - /// static variables. - final GlobalKey keySEDateFilter = - GlobalKey(debugLabel: "EventScreenDateFilter"); - - /// static variables. - final GlobalKey keySEAdd = GlobalKey(debugLabel: "EventScreenAdd"); - - /// static variables. - final GlobalKey keySECard = GlobalKey(debugLabel: "EventScreenCard"); - - /// static variables. - final GlobalKey keyBNPost = GlobalKey(debugLabel: "PostTab"); - - /// static variables. - final GlobalKey keyBNDemoPost = GlobalKey(debugLabel: "DemoPostTab"); - - /// static variables. - final GlobalKey keyBNChat = GlobalKey(debugLabel: "ChatTab"); - - /// static variables. - final GlobalKey keyBNProfile = GlobalKey(debugLabel: "ProfileTab"); - - /// static variables. - final GlobalKey keyBNDemoProfile = GlobalKey(debugLabel: "DemoProfileTab"); - - /// static variables. - final GlobalKey keySPEditProfile = GlobalKey(debugLabel: "ProfileScreenEdit"); - - /// static variables. - final GlobalKey keySPAppSetting = - GlobalKey(debugLabel: "ProfileScreenAppSetting"); - - /// static variables. - final GlobalKey keySPHelp = GlobalKey(debugLabel: "ProfileScreenHelp"); - - /// static variables. - final GlobalKey keySPDonateUs = - GlobalKey(debugLabel: "ProfileScreenDonateUs"); - - /// static variables. - final GlobalKey keySPInvite = GlobalKey(debugLabel: "ProfileScreenInvite"); - - /// static variables. - final GlobalKey keySPLogout = GlobalKey(debugLabel: "ProfileScreenLogout"); - - /// static variables. - final GlobalKey keySPPalisadoes = - GlobalKey(debugLabel: "ProfileScreenPalisadoes"); - - /// bool to determine if we wanna show the apptour. - late bool showAppTour; - - /// bool to determine if apptour is complete. - bool tourComplete = false; - - /// bool to determine if apptour is skipped. - bool tourSkipped = false; - - /// context consist of parent info. - late BuildContext context; - - /// tutorialCoachMark consist of coach used to give tutorial. - late AppTour appTour = AppTour(model: this); - - /// array of target. - final List targets = []; - - /// flag to represent if app is in demoMode. - bool demoMode = false; - - /// flag to represent if app is in testMode. - bool testMode = false; - - /// Initalizing function. - /// - /// **params**: - /// * `ctx`: BuildContext, contain parent info - /// * `fromSignUp`: Bool to find user entry - /// * `mainScreenIndex`: Index to find tab on mainScreen - /// - /// **returns**: - /// None - void initialise( - BuildContext ctx, { - required bool fromSignUp, - required int mainScreenIndex, - bool demoMode = false, - bool testMode = false, - }) { - this.testMode = testMode; - this.demoMode = demoMode; - currentPageIndex = mainScreenIndex; - showAppTour = fromSignUp || demoMode; - context = ctx; - - print(ctx); - print(context); - pluginPrototypeData = { - "Donation": { - "icon": Icons.attach_money_outlined, - "page": const ChangeThemeTile(), - }, - }; - - notifyListeners(); - if (!showAppTour) { - tourComplete = true; - tourSkipped = false; - } else { - Future.delayed( - const Duration(seconds: 1), - () => navigationService.pushDialog( - appTourDialog(ctx), - ), - ); - } - } - - /// Contains the Widgets to be rendered for corresponding navbar items. - /// - /// Features that should be implemented as plugins should be kept here. - List pages = []; - - /// Actual [BottomNavigationBarItem]s that show up on the screen. - List navBarItems = []; - - /// Maps the feature names with their proper Icon and Page. - /// - /// `icon` contains the [IconData] corresponding to plugin's icon. - /// `page` contains the corresponding page to be displayed. - /// Name of the feature provided by the admin must [exactly] match with the. - /// name stored here. - Map pluginPrototypeData = {}; - - /// list of all the pluginList. - List pluginList = []; - - /// Dynamically adds [BottomNavigationBarItems] in `BottomNavigationBar`. - /// - /// by mapping over the data received from the server. - /// - /// **params**: - /// * `context`: its the same context you use everywhere in the flutter framework refer flutter docs for more info. - /// - /// **returns**: - /// None - void fetchAndAddPlugins( - BuildContext context, - ) { - navBarItems = [ - BottomNavigationBarItem( - icon: Icon( - Icons.home, - key: keyBNHome, - ), - label: AppLocalizations.of(context)!.strictTranslate('Home'), - ), - BottomNavigationBarItem( - icon: Icon( - Icons.event_note, - key: keyBNEvents, - ), - label: AppLocalizations.of(context)!.strictTranslate('Events'), - ), - - /// Makes chat inaccessible for the user - //TODO: add chat functionality - // BottomNavigationBarItem( - // icon: Icon( - // Icons.chat_outlined, - // key: keyBNChat, - // ), - // label: AppLocalizations.of(context)!.strictTranslate('Chat'), - // ), - BottomNavigationBarItem( - icon: Icon( - Icons.account_circle, - key: keyBNProfile, - ), - label: AppLocalizations.of(context)!.strictTranslate('Profile'), - ), - ]; - - if (!demoMode) { - pages = [ - OrganizationFeed( - key: const Key("HomeView"), - homeModel: this, - ), - ExploreEvents( - key: const Key('ExploreEvents'), - homeModel: this, - ), - // AddPost( - // key: const Key('AddPost'), - // drawerKey: MainScreenViewModel.scaffoldKey, - // ), - // const ChatPage( - // key: Key('Chats'), - // ), - ProfilePage( - key: keySPEditProfile, - homeModel: this, - ), - ]; - pluginList = - (Hive.box('pluginBox').get('plugins') ?? []) as List; - - print(pluginPrototypeData); - pluginList.forEach((plugin) { - if (pluginPrototypeData.containsKey( - (plugin as Map)["pluginName"] as String, - ) && - plugin["pluginInstallStatus"] as bool) { - navBarItems.add( - BottomNavigationBarItem( - icon: Icon( - (pluginPrototypeData[plugin["pluginName"]] - as Map)["icon"] as IconData, - ), - label: AppLocalizations.of(context)!.strictTranslate( - plugin["pluginName"] as String, - ), - ), - ); - pages.add( - (pluginPrototypeData[plugin["pluginName"]] - as Map)["class"] as StatelessWidget, - ); - } - }); - - /// Causes the app check the plugins updates in every 300 sec - /// - /// updated and re-render the navbar - Timer.periodic(Duration(seconds: (testMode ? 1 : 300)), (timer) { - FetchPluginList(); - final newPluginList = - (Hive.box('pluginBox').get('plugins') ?? []) as List; - - if (listEquals(pluginList, newPluginList)) { - // notifyListeners(); - } - if (testMode) timer.cancel(); - }); - } else { - pages = [ - DemoOrganizationFeed( - key: const Key("DemoHomeView"), - homeModel: this, - ), - DemoExploreEvents( - key: const Key('DemoExploreEvents'), - homeModel: this, - ), - // DemoAddPost( - // key: const Key('DemoAddPost'), - // drawerKey: MainScreenViewModel.scaffoldKey, - // ), - // const ChatPage( - // key: Key('Chats'), - // ), - DemoProfilePage( - key: const Key('DemoProfile'), - homeModel: this, - ), - ]; - } - } - - /// var for current page in index. - int currentPageIndex = 0; - - /// Handles click on [BottomNavigationBarItem]. - /// - /// **params**: - /// * `index`: it is track of current page index. - /// - /// **returns**: - /// None - void onTabTapped(int index) { - currentPageIndex = index; - notifyListeners(); - } - - Widget appTourDialog(BuildContext ctx) { - return CustomAlertDialog( - dialogTitle: 'App Tour', - dialogSubTitle: 'Start app tour to know talawa functioning', - successText: 'Start', - secondaryButtonText: 'Skip', - success: () { - navigationService.pop(); - print(MainScreenViewModel.scaffoldKey.currentState?.isDrawerOpen); - if (MainScreenViewModel.scaffoldKey.currentState?.isDrawerOpen ?? - false) { - MainScreenViewModel.scaffoldKey.currentState?.closeDrawer(); - } - tourHomeTargets(); - }, - secondaryButtonTap: () { - tourComplete = false; - tourSkipped = true; - navigationService.pop(); - notifyListeners(); - }, - ); - } - - /// this functions starts the tour and info to be displayed is mentioned in this functions. - /// - /// **params**: - /// None - /// - /// **returns**: - /// None - void tourHomeTargets() { - targets.clear(); - targets.add( - FocusTarget( - key: keySHOrgName, - keyName: 'keySHOrgName', - description: 'Current selected Organization Name', - appTour: appTour, - ), - ); - targets.add( - FocusTarget( - key: keySHMenuIcon, - keyName: 'keySHMenuIcon', - description: - 'Click this button to see options related to switching, joining and leaving organization(s)', - isCircle: true, - next: () => scaffoldKey.currentState!.openDrawer(), - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keyDrawerCurOrg, - keyName: 'keyDrawerCurOrg', - description: "Current selected Organization's Name appears here", - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keyDrawerSwitchableOrg, - keyName: 'keyDrawerSwitchableOrg', - description: - "All your joined organizations appear over here you can click on them to change the current organization", - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keyDrawerJoinOrg, - keyName: 'keyDrawerJoinOrg', - description: "From this button you can join other listed organizations", - appTour: appTour, - align: ContentAlign.top, - next: () { - if (!userConfig.loggedIn) { - navigationService.pop(); - } - }, - ), - ); - - if (userConfig.loggedIn) { - targets.add( - FocusTarget( - key: keyDrawerLeaveCurrentOrg, - keyName: 'keyDrawerLeaveCurrentOrg', - description: - "To leave the current organization you can use this option", - align: ContentAlign.top, - next: () => navigationService.pop(), - appTour: appTour, - ), - ); - } - - targets.add( - FocusTarget( - key: keyBNHome, - keyName: 'keyBNHome', - description: - "This is the home tab here you can see the latest post from other members of the current organization", - isCircle: true, - align: ContentAlign.top, - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySHPinnedPost, - keyName: 'keySHPinnedPost', - description: - "This section displays all the important post set by the organization admin(s)", - align: ContentAlign.bottom, - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySHPost, - keyName: 'keySHPost', - description: - "This is the post card you can like and comment on the post from the options available", - align: ContentAlign.bottom, - appTour: appTour, - ), - ); - appTour.showTutorial( - onClickTarget: showHome, - onFinish: () { - onTabTapped(currentPageIndex + 1); - if (!tourComplete && !tourSkipped) { - tourEventTargets(); - } - }, - targets: targets, - ); - } - - /// This function shows the Home screen. - /// - /// **params**: - /// * `clickedTarget`: object to identify clickedTarget. - /// - /// **returns**: - /// None - void showHome(TargetFocus clickedTarget) { - switch (clickedTarget.identify) { - case "keySHMenuIcon": - scaffoldKey.currentState!.openDrawer(); - break; - case "keyDrawerLeaveCurrentOrg": - navigationService.pop(); - } - } - - /// This function show the tutorial for Events. - /// - /// **params**: - /// None - /// - /// **returns**: - /// None - void tourEventTargets() { - targets.clear(); - targets.add( - FocusTarget( - key: keyBNEvents, - keyName: 'keyBNEvents', - description: - 'This is the Events tab here you can see all event related information of the current selected organization', - isCircle: true, - align: ContentAlign.top, - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySECategoryMenu, - keyName: 'keySECategoryMenu', - description: 'Filter Events based on categories', - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySEDateFilter, - keyName: 'keySEDateFilter', - description: 'Filter Events between selected dates', - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySECard, - keyName: 'keySECard', - description: - 'Description of event to see more details click on the card', - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySEAdd, - keyName: 'keySEAdd', - description: 'You can create a new event from here', - align: ContentAlign.top, - appTour: appTour, - ), - ); - - appTour.showTutorial( - onFinish: () { - onTabTapped(currentPageIndex + 1); - if (!tourComplete && !tourSkipped) { - tourProfile(); - } - }, - onClickTarget: (TargetFocus a) {}, - targets: targets, - ); - } - - /// This function show the tutorial to add Post in the organization. - /// - /// **params**: - /// None - /// - /// **returns**: - /// None - void tourAddPost() { - targets.clear(); - targets.add( - FocusTarget( - key: keyBNPost, - keyName: 'keyBNPost', - description: - 'This is the Create post tab here you can add post to the current selected organization', - isCircle: true, - align: ContentAlign.top, - appTour: appTour, - ), - ); - appTour.showTutorial( - onFinish: () { - onTabTapped(currentPageIndex + 1); - if (!tourComplete && !tourSkipped) { - // tourChat(); - tourProfile(); - } - }, - onClickTarget: (TargetFocus a) {}, - targets: targets, - ); - } - - /// This function show the tour of chats. - /// - /// **params**: - /// None - /// - /// **returns**: - /// None - void tourChat() { - targets.clear(); - targets.add( - FocusTarget( - key: keyBNChat, - keyName: 'keyBNChat', - description: - 'This is the Chat tab here you can see all your messages of the current selected organization', - isCircle: true, - align: ContentAlign.top, - appTour: appTour, - ), - ); - appTour.showTutorial( - onFinish: () { - onTabTapped(currentPageIndex + 1); - if (!tourComplete && !tourSkipped) { - tourProfile(); - } - }, - onClickTarget: (TargetFocus a) {}, - targets: targets, - ); - } - - /// This function show the tutorial for the profile page. - /// - /// **params**: - /// None - /// - /// **returns**: - /// None - void tourProfile() { - targets.clear(); - targets.add( - FocusTarget( - key: keyBNProfile, - keyName: 'keyBNProfile', - description: - 'This is the Profile tab here you can see all options related to account, app setting, invitation, help etc', - isCircle: true, - align: ContentAlign.top, - nextCrossAlign: CrossAxisAlignment.start, - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySPAppSetting, - keyName: 'keySPAppSetting', - description: - 'You can edit application settings like language, theme etc from here', - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySPHelp, - keyName: 'keySPHelp', - description: - 'For any help we are always there. You can reach us from here', - appTour: appTour, - ), - ); - - targets.add( - FocusTarget( - key: keySPDonateUs, - keyName: 'keySPDonateUs', - description: - 'To help your organization grow you can support them financially from here', - appTour: appTour, - ), - ); - -// Uncomment the section below if you want to add the keySPInvite target -// targets.add( -// FocusTarget( -// key: keySPInvite, -// keyName: 'keySPInvite', -// description: 'Wanna invite colleague, invite them from here', -// ), -// ); - - targets.add( - FocusTarget( - key: keySPPalisadoes, - keyName: 'keySPPalisadoes', - description: 'You are all set to go lets get you in', - isEnd: true, - appTour: appTour, - ), - ); - - appTour.showTutorial( - onFinish: () { - if (!tourComplete && !tourSkipped) { - tourComplete = true; - onTabTapped(0); - } - }, - onClickTarget: (TargetFocus a) {}, - targets: targets, - ); - } -} +import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:hive/hive.dart'; +import 'package:talawa/locator.dart'; +import 'package:talawa/models/app_tour.dart'; +import 'package:talawa/plugins/fetch_plugin_list.dart'; +import 'package:talawa/utils/app_localization.dart'; +import 'package:talawa/view_model/base_view_model.dart'; +// import 'package:talawa/views/after_auth_screens/chat/chat_list_screen.dart'; +import 'package:talawa/views/after_auth_screens/events/explore_events.dart'; +import 'package:talawa/views/after_auth_screens/feed/organization_feed.dart'; +import 'package:talawa/views/after_auth_screens/profile/profile_page.dart'; +import 'package:talawa/views/demo_screens/explore_events_demo.dart'; +import 'package:talawa/views/demo_screens/organization_feed_demo.dart'; +import 'package:talawa/views/demo_screens/profile_page_demo.dart'; +import 'package:talawa/widgets/custom_alert_dialog.dart'; +import 'package:talawa/widgets/theme_switch.dart'; +import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; + +/// MainScreenViewModel class provide methods to interact with the modal to serve data in user's action in Main Screen Views. +/// +/// The functions in this class are +/// mainly in the context of Tutorials for different componenets of the App. +/// +/// Functions include: +/// * `showTutorial` +/// * `showHome` +/// * `tourEventTargets` +/// * `tourAddPost` +/// * `tourChat` +/// * `tourProfile` +class MainScreenViewModel extends BaseModel { + /// static variables. + static final GlobalKey scaffoldKey = + GlobalKey(); + + /// static variables. + final GlobalKey keyBNHome = GlobalKey(debugLabel: "HomeTab"); + + /// static variables. + final GlobalKey keyBNDemoHome = GlobalKey(debugLabel: "DemoHomeTab"); + + /// static variables. + final GlobalKey keySHPinnedPost = + GlobalKey(debugLabel: "HomeScreenPinnedPost"); + + /// static variables. + final GlobalKey keySHPost = GlobalKey(debugLabel: "HomeScreenPost"); + + /// static variables. + final GlobalKey keySHOrgName = GlobalKey(debugLabel: "HomeScreenOrgName"); + + /// static variables. + final GlobalKey keySHMenuIcon = GlobalKey(debugLabel: "HomeScreenMenuIcon"); + + /// static variables. + static final GlobalKey keyDrawerCurOrg = + GlobalKey(debugLabel: "DrawerCurrentOrg"); + + /// static variables. + static final GlobalKey keyDrawerSwitchableOrg = + GlobalKey(debugLabel: "DrawerSwitchableOrg"); + + /// static variables. + static final GlobalKey keyDrawerJoinOrg = + GlobalKey(debugLabel: "DrawerJoinOrg"); + + /// static variables. + static final GlobalKey keyDrawerLeaveCurrentOrg = + GlobalKey(debugLabel: "DrawerLeaveCurrentOr"); + + /// static variables. + final GlobalKey keyBNEvents = GlobalKey(debugLabel: "EventTab"); + + /// static variables. + final GlobalKey keyBNDemoEvents = GlobalKey(debugLabel: "DemoEventTab"); + + /// static variables. + final GlobalKey keySECategoryMenu = + GlobalKey(debugLabel: "EventScreenCategory"); + + /// static variables. + final GlobalKey keySEDateFilter = + GlobalKey(debugLabel: "EventScreenDateFilter"); + + /// static variables. + final GlobalKey keySEAdd = GlobalKey(debugLabel: "EventScreenAdd"); + + /// static variables. + final GlobalKey keySECard = GlobalKey(debugLabel: "EventScreenCard"); + + /// static variables. + final GlobalKey keyBNPost = GlobalKey(debugLabel: "PostTab"); + + /// static variables. + final GlobalKey keyBNDemoPost = GlobalKey(debugLabel: "DemoPostTab"); + + /// static variables. + final GlobalKey keyBNChat = GlobalKey(debugLabel: "ChatTab"); + + /// static variables. + final GlobalKey keyBNProfile = GlobalKey(debugLabel: "ProfileTab"); + + /// static variables. + final GlobalKey keyBNDemoProfile = GlobalKey(debugLabel: "DemoProfileTab"); + + /// static variables. + final GlobalKey keySPEditProfile = GlobalKey(debugLabel: "ProfileScreenEdit"); + + /// static variables. + final GlobalKey keySPAppSetting = + GlobalKey(debugLabel: "ProfileScreenAppSetting"); + + /// static variables. + final GlobalKey keySPHelp = GlobalKey(debugLabel: "ProfileScreenHelp"); + + /// static variables. + final GlobalKey keySPDonateUs = + GlobalKey(debugLabel: "ProfileScreenDonateUs"); + + /// static variables. + final GlobalKey keySPInvite = GlobalKey(debugLabel: "ProfileScreenInvite"); + + /// static variables. + final GlobalKey keySPLogout = GlobalKey(debugLabel: "ProfileScreenLogout"); + + /// static variables. + final GlobalKey keySPPalisadoes = + GlobalKey(debugLabel: "ProfileScreenPalisadoes"); + + /// bool to determine if we wanna show the apptour. + late bool showAppTour; + + /// bool to determine if apptour is complete. + bool tourComplete = false; + + /// bool to determine if apptour is skipped. + bool tourSkipped = false; + + /// context consist of parent info. + late BuildContext context; + + /// tutorialCoachMark consist of coach used to give tutorial. + late AppTour appTour = AppTour(model: this); + + /// array of target. + final List targets = []; + + /// flag to represent if app is in demoMode. + bool demoMode = false; + + /// flag to represent if app is in testMode. + bool testMode = false; + + /// Initalizing function. + /// + /// **params**: + /// * `ctx`: BuildContext, contain parent info + /// * `fromSignUp`: Bool to find user entry + /// * `mainScreenIndex`: Index to find tab on mainScreen + /// + /// **returns**: + /// None + void initialise( + BuildContext ctx, { + required bool fromSignUp, + required int mainScreenIndex, + bool demoMode = false, + bool testMode = false, + }) { + this.testMode = testMode; + this.demoMode = demoMode; + currentPageIndex = mainScreenIndex; + showAppTour = fromSignUp || demoMode; + context = ctx; + + print(ctx); + print(context); + pluginPrototypeData = { + "Donation": { + "icon": Icons.attach_money_outlined, + "page": const ChangeThemeTile(), + }, + }; + + notifyListeners(); + if (!showAppTour) { + tourComplete = true; + tourSkipped = false; + } else { + Future.delayed( + const Duration(seconds: 1), + () => navigationService.pushDialog( + appTourDialog(ctx), + ), + ); + } + } + + /// Contains the Widgets to be rendered for corresponding navbar items. + /// + /// Features that should be implemented as plugins should be kept here. + List pages = []; + + /// Actual [BottomNavigationBarItem]s that show up on the screen. + List navBarItems = []; + + /// Maps the feature names with their proper Icon and Page. + /// + /// `icon` contains the [IconData] corresponding to plugin's icon. + /// `page` contains the corresponding page to be displayed. + /// Name of the feature provided by the admin must [exactly] match with the. + /// name stored here. + Map pluginPrototypeData = {}; + + /// list of all the pluginList. + List pluginList = []; + + /// Dynamically adds [BottomNavigationBarItems] in `BottomNavigationBar`. + /// + /// by mapping over the data received from the server. + /// + /// **params**: + /// * `context`: its the same context you use everywhere in the flutter framework refer flutter docs for more info. + /// + /// **returns**: + /// None + void fetchAndAddPlugins( + BuildContext context, + ) { + navBarItems = [ + BottomNavigationBarItem( + icon: Icon( + Icons.home, + key: keyBNHome, + ), + label: AppLocalizations.of(context)!.strictTranslate('Home'), + ), + BottomNavigationBarItem( + icon: Icon( + Icons.event_note, + key: keyBNEvents, + ), + label: AppLocalizations.of(context)!.strictTranslate('Events'), + ), + + /// Makes chat inaccessible for the user + //TODO: add chat functionality + // BottomNavigationBarItem( + // icon: Icon( + // Icons.chat_outlined, + // key: keyBNChat, + // ), + // label: AppLocalizations.of(context)!.strictTranslate('Chat'), + // ), + BottomNavigationBarItem( + icon: Icon( + Icons.account_circle, + key: keyBNProfile, + ), + label: AppLocalizations.of(context)!.strictTranslate('Profile'), + ), + ]; + + if (!demoMode) { + pages = [ + OrganizationFeed( + key: const Key("HomeView"), + homeModel: this, + ), + ExploreEvents( + key: const Key('ExploreEvents'), + homeModel: this, + ), + // AddPost( + // key: const Key('AddPost'), + // drawerKey: MainScreenViewModel.scaffoldKey, + // ), + // const ChatPage( + // key: Key('Chats'), + // ), + ProfilePage( + key: keySPEditProfile, + homeModel: this, + ), + ]; + pluginList = + (Hive.box('pluginBox').get('plugins') ?? []) as List; + + print(pluginPrototypeData); + pluginList.forEach((plugin) { + if (pluginPrototypeData.containsKey( + (plugin as Map)["pluginName"] as String, + ) && + plugin["pluginInstallStatus"] as bool) { + navBarItems.add( + BottomNavigationBarItem( + icon: Icon( + (pluginPrototypeData[plugin["pluginName"]] + as Map)["icon"] as IconData, + ), + label: AppLocalizations.of(context)!.strictTranslate( + plugin["pluginName"] as String, + ), + ), + ); + pages.add( + (pluginPrototypeData[plugin["pluginName"]] + as Map)["class"] as StatelessWidget, + ); + } + }); + + /// Causes the app check the plugins updates in every 300 sec + /// + /// updated and re-render the navbar + Timer.periodic(Duration(seconds: (testMode ? 1 : 300)), (timer) { + FetchPluginList(); + final newPluginList = + (Hive.box('pluginBox').get('plugins') ?? []) as List; + + if (listEquals(pluginList, newPluginList)) { + // notifyListeners(); + } + if (testMode) timer.cancel(); + }); + } else { + pages = [ + DemoOrganizationFeed( + key: const Key("DemoHomeView"), + homeModel: this, + ), + DemoExploreEvents( + key: const Key('DemoExploreEvents'), + homeModel: this, + ), + // DemoAddPost( + // key: const Key('DemoAddPost'), + // drawerKey: MainScreenViewModel.scaffoldKey, + // ), + // const ChatPage( + // key: Key('Chats'), + // ), + DemoProfilePage( + key: const Key('DemoProfile'), + homeModel: this, + ), + ]; + } + } + + /// var for current page in index. + int currentPageIndex = 0; + + /// Handles click on [BottomNavigationBarItem]. + /// + /// **params**: + /// * `index`: it is track of current page index. + /// + /// **returns**: + /// None + void onTabTapped(int index) { + currentPageIndex = index; + notifyListeners(); + } + + Widget appTourDialog(BuildContext ctx) { + return CustomAlertDialog( + dialogTitle: 'App Tour', + dialogSubTitle: 'Start app tour to know talawa functioning', + successText: 'Start', + secondaryButtonText: 'Skip', + success: () { + navigationService.pop(); + print(MainScreenViewModel.scaffoldKey.currentState?.isDrawerOpen); + if (MainScreenViewModel.scaffoldKey.currentState?.isDrawerOpen ?? + false) { + MainScreenViewModel.scaffoldKey.currentState?.closeDrawer(); + } + tourHomeTargets(); + }, + secondaryButtonTap: () { + tourComplete = false; + tourSkipped = true; + navigationService.pop(); + notifyListeners(); + }, + ); + } + + /// this functions starts the tour and info to be displayed is mentioned in this functions. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None + void tourHomeTargets() { + targets.clear(); + targets.add( + FocusTarget( + key: keySHOrgName, + keyName: 'keySHOrgName', + description: 'Current selected Organization Name', + appTour: appTour, + ), + ); + targets.add( + FocusTarget( + key: keySHMenuIcon, + keyName: 'keySHMenuIcon', + description: + 'Click this button to see options related to switching, joining and leaving organization(s)', + isCircle: true, + next: () => scaffoldKey.currentState!.openDrawer(), + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keyDrawerCurOrg, + keyName: 'keyDrawerCurOrg', + description: "Current selected Organization's Name appears here", + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keyDrawerSwitchableOrg, + keyName: 'keyDrawerSwitchableOrg', + description: + "All your joined organizations appear over here you can click on them to change the current organization", + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keyDrawerJoinOrg, + keyName: 'keyDrawerJoinOrg', + description: "From this button you can join other listed organizations", + appTour: appTour, + align: ContentAlign.top, + next: () { + if (!userConfig.loggedIn) { + navigationService.pop(); + } + }, + ), + ); + + if (userConfig.loggedIn) { + targets.add( + FocusTarget( + key: keyDrawerLeaveCurrentOrg, + keyName: 'keyDrawerLeaveCurrentOrg', + description: + "To leave the current organization you can use this option", + align: ContentAlign.top, + next: () => navigationService.pop(), + appTour: appTour, + ), + ); + } + + targets.add( + FocusTarget( + key: keyBNHome, + keyName: 'keyBNHome', + description: + "This is the home tab here you can see the latest post from other members of the current organization", + isCircle: true, + align: ContentAlign.top, + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySHPinnedPost, + keyName: 'keySHPinnedPost', + description: + "This section displays all the important post set by the organization admin(s)", + align: ContentAlign.bottom, + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySHPost, + keyName: 'keySHPost', + description: + "This is the post card you can like and comment on the post from the options available", + align: ContentAlign.bottom, + appTour: appTour, + ), + ); + appTour.showTutorial( + onClickTarget: showHome, + onFinish: () { + onTabTapped(currentPageIndex + 1); + if (!tourComplete && !tourSkipped) { + tourEventTargets(); + } + }, + targets: targets, + ); + } + + /// This function shows the Home screen. + /// + /// **params**: + /// * `clickedTarget`: object to identify clickedTarget. + /// + /// **returns**: + /// None + void showHome(TargetFocus clickedTarget) { + switch (clickedTarget.identify) { + case "keySHMenuIcon": + scaffoldKey.currentState!.openDrawer(); + break; + case "keyDrawerLeaveCurrentOrg": + navigationService.pop(); + } + } + + /// This function show the tutorial for Events. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None + void tourEventTargets() { + targets.clear(); + targets.add( + FocusTarget( + key: keyBNEvents, + keyName: 'keyBNEvents', + description: + 'This is the Events tab here you can see all event related information of the current selected organization', + isCircle: true, + align: ContentAlign.top, + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySECategoryMenu, + keyName: 'keySECategoryMenu', + description: 'Filter Events based on categories', + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySEDateFilter, + keyName: 'keySEDateFilter', + description: 'Filter Events between selected dates', + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySECard, + keyName: 'keySECard', + description: + 'Description of event to see more details click on the card', + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySEAdd, + keyName: 'keySEAdd', + description: 'You can create a new event from here', + align: ContentAlign.top, + appTour: appTour, + ), + ); + + appTour.showTutorial( + onFinish: () { + onTabTapped(currentPageIndex + 1); + if (!tourComplete && !tourSkipped) { + tourProfile(); + } + }, + onClickTarget: (TargetFocus a) {}, + targets: targets, + ); + } + + /// This function show the tutorial to add Post in the organization. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None + void tourAddPost() { + targets.clear(); + targets.add( + FocusTarget( + key: keyBNPost, + keyName: 'keyBNPost', + description: + 'This is the Create post tab here you can add post to the current selected organization', + isCircle: true, + align: ContentAlign.top, + appTour: appTour, + ), + ); + appTour.showTutorial( + onFinish: () { + onTabTapped(currentPageIndex + 1); + if (!tourComplete && !tourSkipped) { + // tourChat(); + tourProfile(); + } + }, + onClickTarget: (TargetFocus a) {}, + targets: targets, + ); + } + + /// This function show the tour of chats. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None + void tourChat() { + targets.clear(); + targets.add( + FocusTarget( + key: keyBNChat, + keyName: 'keyBNChat', + description: + 'This is the Chat tab here you can see all your messages of the current selected organization', + isCircle: true, + align: ContentAlign.top, + appTour: appTour, + ), + ); + appTour.showTutorial( + onFinish: () { + onTabTapped(currentPageIndex + 1); + if (!tourComplete && !tourSkipped) { + tourProfile(); + } + }, + onClickTarget: (TargetFocus a) {}, + targets: targets, + ); + } + + /// This function show the tutorial for the profile page. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None + void tourProfile() { + targets.clear(); + targets.add( + FocusTarget( + key: keyBNProfile, + keyName: 'keyBNProfile', + description: + 'This is the Profile tab here you can see all options related to account, app setting, invitation, help etc', + isCircle: true, + align: ContentAlign.top, + nextCrossAlign: CrossAxisAlignment.start, + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySPAppSetting, + keyName: 'keySPAppSetting', + description: + 'You can edit application settings like language, theme etc from here', + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySPHelp, + keyName: 'keySPHelp', + description: + 'For any help we are always there. You can reach us from here', + appTour: appTour, + ), + ); + + targets.add( + FocusTarget( + key: keySPDonateUs, + keyName: 'keySPDonateUs', + description: + 'To help your organization grow you can support them financially from here', + appTour: appTour, + ), + ); + +// Uncomment the section below if you want to add the keySPInvite target +// targets.add( +// FocusTarget( +// key: keySPInvite, +// keyName: 'keySPInvite', +// description: 'Wanna invite colleague, invite them from here', +// ), +// ); + + targets.add( + FocusTarget( + key: keySPPalisadoes, + keyName: 'keySPPalisadoes', + description: 'You are all set to go lets get you in', + isEnd: true, + appTour: appTour, + ), + ); + + appTour.showTutorial( + onFinish: () { + if (!tourComplete && !tourSkipped) { + tourComplete = true; + onTabTapped(0); + } + }, + onClickTarget: (TargetFocus a) {}, + targets: targets, + ); + } +} diff --git a/lib/views/after_auth_screens/add_post_page.dart b/lib/views/after_auth_screens/add_post_page.dart index 028f751a9d..9ec32746c7 100644 --- a/lib/views/after_auth_screens/add_post_page.dart +++ b/lib/views/after_auth_screens/add_post_page.dart @@ -118,7 +118,10 @@ class _AddPostState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: const Text("Enter the Tag"), + title: Text( + AppLocalizations.of(context)! + .strictTranslate("Enter the Tag"), + ), content: TextField( controller: model.textHashTagController, ), @@ -132,14 +135,20 @@ class _AddPostState extends State { ); Navigator.of(context).pop(); }, - child: const Text("Add"), + child: Text( + AppLocalizations.of(context)! + .strictTranslate("Add"), + ), ), TextButton( key: const Key("cancel_hashtag_button"), onPressed: () { Navigator.of(context).pop(); }, - child: const Text("Cancel"), + child: Text( + AppLocalizations.of(context)! + .strictTranslate("Cancel"), + ), ), ], ); diff --git a/lib/views/after_auth_screens/events/create_event_form.dart b/lib/views/after_auth_screens/events/create_event_form.dart index 30c31db7f9..440a608c3a 100644 --- a/lib/views/after_auth_screens/events/create_event_form.dart +++ b/lib/views/after_auth_screens/events/create_event_form.dart @@ -1,6 +1,3 @@ -// ignore_for_file: talawa_api_doc -// ignore_for_file: talawa_good_doc_comments - import 'package:flutter/material.dart'; import 'package:talawa/constants/routing_constants.dart'; import 'package:talawa/locator.dart'; @@ -33,7 +30,8 @@ class CreateEventForm extends StatelessWidget { validator: (value) => Validator.validateEventForm(value!, 'Title'), decoration: InputDecoration( // placeholder of the text field - labelText: 'Add Event Title', + labelText: AppLocalizations.of(context)! + .strictTranslate('Add Event Title'), isDense: true, labelStyle: Theme.of(context).textTheme.titleMedium, focusedBorder: InputBorder.none, @@ -65,8 +63,10 @@ class CreateEventForm extends StatelessWidget { validator: (value) => Validator.validateEventForm(value!, 'Location'), decoration: InputDecoration( - hintText: 'Where is the event?', - labelText: 'Add Location', + hintText: AppLocalizations.of(context)! + .strictTranslate('Where is the event?'), + labelText: + AppLocalizations.of(context)!.strictTranslate('Add Location'), labelStyle: Theme.of(context).textTheme.titleMedium, border: InputBorder.none, focusedBorder: InputBorder.none, @@ -118,8 +118,10 @@ class CreateEventForm extends StatelessWidget { maxLines: 10, minLines: 1, decoration: InputDecoration( - hintText: 'Describe the event', - labelText: 'Add Description', + hintText: AppLocalizations.of(context)! + .strictTranslate('Describe the event'), + labelText: AppLocalizations.of(context)! + .strictTranslate('Add Description'), labelStyle: Theme.of(context).textTheme.titleMedium, border: InputBorder.none, focusedBorder: InputBorder.none, diff --git a/lib/views/after_auth_screens/events/create_event_page.dart b/lib/views/after_auth_screens/events/create_event_page.dart index 608f9975c9..c3e7e84efb 100644 --- a/lib/views/after_auth_screens/events/create_event_page.dart +++ b/lib/views/after_auth_screens/events/create_event_page.dart @@ -335,7 +335,11 @@ class _CreateEventPageState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Add Members", style: subtitleTextStyle), + Text( + AppLocalizations.of(context)! + .strictTranslate("Add Members"), + style: subtitleTextStyle, + ), Icon( Icons.add, color: Theme.of(context).colorScheme.secondary, diff --git a/lib/views/after_auth_screens/events/explore_events.dart b/lib/views/after_auth_screens/events/explore_events.dart index cc9d665df7..119b315536 100644 --- a/lib/views/after_auth_screens/events/explore_events.dart +++ b/lib/views/after_auth_screens/events/explore_events.dart @@ -242,7 +242,12 @@ class ExploreEvents extends StatelessWidget { ? SizedBox( height: SizeConfig.screenHeight! * 0.5, child: Center( - child: Text(model.emptyListMessage), + child: Text( + AppLocalizations.of(context)! + .strictTranslate( + model.emptyListMessage, + ), + ), ), ) : ListView.builder( diff --git a/lib/views/after_auth_screens/feed/individual_post.dart b/lib/views/after_auth_screens/feed/individual_post.dart index 6a1033a5eb..d2be8c3469 100644 --- a/lib/views/after_auth_screens/feed/individual_post.dart +++ b/lib/views/after_auth_screens/feed/individual_post.dart @@ -1,6 +1,3 @@ -// ignore_for_file: talawa_api_doc -// ignore_for_file: talawa_good_doc_comments - import 'package:flutter/material.dart'; import 'package:talawa/models/comment/comment_model.dart'; import 'package:talawa/models/post/post_model.dart'; @@ -48,9 +45,11 @@ class _IndividualPostViewState extends State { _controller.text = ""; }, textAlign: TextAlign.start, - decoration: const InputDecoration( - hintText: "Write your comment here..", - contentPadding: EdgeInsets.all(8.0), + decoration: InputDecoration( + hintText: AppLocalizations.of(context)!.strictTranslate( + "Write your comment here..", + ), + contentPadding: const EdgeInsets.all(8.0), focusColor: Colors.black, border: InputBorder.none, ), @@ -63,7 +62,11 @@ class _IndividualPostViewState extends State { _commentViewModel.createComment(_controller.text); _controller.text = ""; }, - child: const Text("Send"), + child: Text( + AppLocalizations.of(context)!.strictTranslate( + "Send", + ), + ), ), ], ), @@ -124,7 +127,12 @@ class IndividualPageLikeSection extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildPadding(context, "Liked by"), + buildPadding( + context, + AppLocalizations.of(context)!.strictTranslate( + "Liked by", + ), + ), Row( children: [ // Looping through the usersLiked list, diff --git a/lib/views/after_auth_screens/join_org_after_auth/join_organisation_after_auth.dart b/lib/views/after_auth_screens/join_org_after_auth/join_organisation_after_auth.dart index a18bfe9960..fa519edbb8 100644 --- a/lib/views/after_auth_screens/join_org_after_auth/join_organisation_after_auth.dart +++ b/lib/views/after_auth_screens/join_org_after_auth/join_organisation_after_auth.dart @@ -129,7 +129,9 @@ class JoinOrganisationAfterAuth extends StatelessWidget { SizedBox( height: SizeConfig.safeBlockVertical! * 4, ), - const Text('Scan QR'), + Text( + AppLocalizations.of(context)!.strictTranslate('Scan QR'), + ), SizedBox( height: SizeConfig.safeBlockVertical! * 4, ), diff --git a/lib/views/after_auth_screens/profile/profile_page.dart b/lib/views/after_auth_screens/profile/profile_page.dart index ab058478d8..787bbd875e 100644 --- a/lib/views/after_auth_screens/profile/profile_page.dart +++ b/lib/views/after_auth_screens/profile/profile_page.dart @@ -84,9 +84,10 @@ class ProfilePage extends StatelessWidget { navigationService .pushScreen("/editProfilePage"); }, - child: const Text( - "Edit Profile", - style: TextStyle( + child: Text( + AppLocalizations.of(context)! + .strictTranslate("Edit Profile"), + style: const TextStyle( fontFamily: 'open-sans', ), ), @@ -99,9 +100,10 @@ class ProfilePage extends StatelessWidget { onPressed: () { model.logout(context); }, - child: const Text( - "Log Out", - style: TextStyle( + child: Text( + AppLocalizations.of(context)! + .strictTranslate("Log Out"), + style: const TextStyle( fontFamily: 'open-sans', ), ), @@ -364,7 +366,7 @@ class ProfilePage extends StatelessWidget { padding: const EdgeInsets.only(top: 8.0), // display title child: Text( - 'Donating to \n${model.currentOrg.name}', + '${AppLocalizations.of(context)!.strictTranslate('Donating to')}\n${model.currentOrg.name}', style: Theme.of(context) .textTheme .headlineMedium! @@ -400,7 +402,8 @@ class ProfilePage extends StatelessWidget { height: SizeConfig.screenWidth! * 0.05, ), Text( - 'Please Select and amount', + AppLocalizations.of(context)! + .strictTranslate('Please Select any amount'), style: Theme.of(context).textTheme.headlineSmall, ), SizedBox( @@ -428,7 +431,8 @@ class ProfilePage extends StatelessWidget { style: Theme.of(context).textTheme.headlineSmall, ), Text( - 'Input custom amount', + AppLocalizations.of(context)! + .strictTranslate('Input custom amount'), style: Theme.of(context).textTheme.headlineSmall, ), SizedBox( diff --git a/lib/views/demo_screens/organization_feed_demo.dart b/lib/views/demo_screens/organization_feed_demo.dart index ec4f9b8496..5b2375d91e 100644 --- a/lib/views/demo_screens/organization_feed_demo.dart +++ b/lib/views/demo_screens/organization_feed_demo.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:talawa/models/post/post_model.dart'; +import 'package:talawa/utils/app_localization.dart'; import 'package:talawa/view_model/main_screen_view_model.dart'; import 'package:talawa/widgets/pinned_post.dart'; @@ -95,7 +96,7 @@ class DemoOrganizationFeed extends StatelessWidget { elevation: 0.0, centerTitle: true, title: Text( - "Organisation Name", + AppLocalizations.of(context)!.strictTranslate("Organisation Name"), key: homeModel?.keySHOrgName, style: Theme.of(context).textTheme.titleLarge!.copyWith( fontSize: 20, diff --git a/lib/views/pre_auth_screens/select_organization.dart b/lib/views/pre_auth_screens/select_organization.dart index 8b5214e298..1c89c39935 100644 --- a/lib/views/pre_auth_screens/select_organization.dart +++ b/lib/views/pre_auth_screens/select_organization.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:talawa/services/size_config.dart'; +import 'package:talawa/utils/app_localization.dart'; import 'package:talawa/view_model/pre_auth_view_models/select_organization_view_model.dart'; import 'package:talawa/views/base_view.dart'; import 'package:talawa/widgets/organization_list.dart'; @@ -36,13 +37,14 @@ class _SelectOrganizationState extends State { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ - const Padding( - padding: EdgeInsets.symmetric( + Padding( + padding: const EdgeInsets.symmetric( horizontal: 18, ), child: Text( - "Choose an Organization", - style: TextStyle(fontSize: 40), + AppLocalizations.of(context)! + .strictTranslate("Choose an Organization"), + style: const TextStyle(fontSize: 40), ), ), Expanded(child: OrganizationList(model: model)), diff --git a/lib/widgets/custom_alert_dialog.dart b/lib/widgets/custom_alert_dialog.dart index e6cc779e8f..74121a8c95 100644 --- a/lib/widgets/custom_alert_dialog.dart +++ b/lib/widgets/custom_alert_dialog.dart @@ -91,7 +91,9 @@ class CustomAlertDialog extends StatelessWidget { .headlineSmall! .copyWith(fontWeight: FontWeight.w800), ), - content: Text(dialogSubTitle), + content: Text( + AppLocalizations.of(context)!.strictTranslate(dialogSubTitle), + ), buttonPadding: EdgeInsets.symmetric( horizontal: SizeConfig.screenWidth! * 0.05, vertical: SizeConfig.screenHeight! * 0.05, diff --git a/lib/widgets/task_form.dart b/lib/widgets/task_form.dart index 25b8cbd37e..f5f3376036 100644 --- a/lib/widgets/task_form.dart +++ b/lib/widgets/task_form.dart @@ -1,6 +1,3 @@ -// ignore_for_file: talawa_api_doc -// ignore_for_file: talawa_good_doc_comments - import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:talawa/locator.dart'; @@ -144,7 +141,8 @@ class TitleField extends StatelessWidget { maxLength: 100, validator: (value) => Validator.validateEventForm(value!, 'Title'), decoration: InputDecoration( - labelText: 'Add Task Title', + labelText: + AppLocalizations.of(context)!.strictTranslate('Add Task Title'), isDense: true, labelStyle: Theme.of(context).textTheme.titleMedium, focusedBorder: InputBorder.none, @@ -182,8 +180,10 @@ class DescriptionField extends StatelessWidget { maxLines: 10, minLines: 1, decoration: InputDecoration( - hintText: 'Describe the task', - labelText: 'Add Description', + hintText: + AppLocalizations.of(context)!.strictTranslate('Describe the task'), + labelText: + AppLocalizations.of(context)!.strictTranslate('Add Description'), labelStyle: Theme.of(context).textTheme.titleMedium, border: InputBorder.none, focusedBorder: InputBorder.none, diff --git a/test/model_tests/app_tour_test.dart b/test/model_tests/app_tour_test.dart index 57579acafa..c65cfb8cb6 100644 --- a/test/model_tests/app_tour_test.dart +++ b/test/model_tests/app_tour_test.dart @@ -10,7 +10,7 @@ import 'package:talawa/view_model/main_screen_view_model.dart'; import 'package:talawa/views/base_view.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; -import '../router_test.dart'; +class MockBuildContext extends Mock implements BuildContext {} class CustomTutorialController extends TutorialCoachMarkController { @override @@ -86,6 +86,7 @@ void main() { testWidgets('Test for showTutorial method.', (tester) async { AppTour? mockAppTour; FocusTarget? mockFocusTarget; + BuildContext? capturedContext; final app = BaseView( onModelReady: (model) => model.initialize(), builder: (context, langModel, child) { @@ -105,6 +106,7 @@ void main() { testMode: true, ), builder: (context, model2, child) { + capturedContext = context; mockAppTour = AppTour(model: model2); mockFocusTarget = FocusTarget( key: MainScreenViewModel.keyDrawerLeaveCurrentOrg, @@ -151,6 +153,7 @@ void main() { expect(tutorialBtn, findsOneWidget); (tester.widget(tutorialBtn) as TextButton).onPressed!(); + await tester.pumpAndSettle(); mockAppTour!.tutorialCoachMark.onSkip!(); mockAppTour!.tutorialCoachMark.onClickOverlay!( @@ -161,7 +164,7 @@ void main() { ); (mockFocusTarget!.focusWidget.contents![1].builder!( - MockBuildContext(), + capturedContext!, CustomTutorialController(), ) as GestureDetector) .onTap!(); diff --git a/test/service_tests/navigation_service_test.dart b/test/service_tests/navigation_service_test.dart index e40d8f17e8..564cc28b56 100644 --- a/test/service_tests/navigation_service_test.dart +++ b/test/service_tests/navigation_service_test.dart @@ -106,6 +106,41 @@ class _HomeAppState extends State { } } +class HomeApp2 extends StatefulWidget { + const HomeApp2({ + super.key, + required this.onClick, + required this.navigateorKey, + }); + final GlobalKey navigateorKey; + final VoidCallback onClick; + + @override + State createState() => _HomeAppState2(); +} + +class _HomeAppState2 extends State { + @override + Widget build(BuildContext context) { + return MaterialApp( + locale: const Locale('en'), + localizationsDelegates: [ + const AppLocalizationsDelegate(isTest: true), + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + navigatorKey: widget.navigateorKey, + initialRoute: '/', + onGenerateRoute: _onGenerateTestRoute, + home: FirstTestScreen( + onClick: () { + widget.onClick(); + }, + ), + ); + } +} + class FirstTestScreen extends StatefulWidget { const FirstTestScreen({super.key, required this.onClick, this.arguments}); final VoidCallback onClick; @@ -441,7 +476,7 @@ void main() { }); testWidgets('showSnackBar() test with default duration', (tester) async { await tester.pumpWidget( - HomeApp( + HomeApp2( navigateorKey: mockKey, onClick: () { navigationService.showSnackBar('Hello Talawa'); @@ -459,7 +494,7 @@ void main() { }); testWidgets('showSnackBar() test with custom duration', (tester) async { await tester.pumpWidget( - HomeApp( + HomeApp2( navigateorKey: mockKey, onClick: () { navigationService.showSnackBar( diff --git a/test/view_model_tests/main_screen_view_model_test.dart b/test/view_model_tests/main_screen_view_model_test.dart index 3d83f41840..19bdf8616e 100644 --- a/test/view_model_tests/main_screen_view_model_test.dart +++ b/test/view_model_tests/main_screen_view_model_test.dart @@ -1,688 +1,688 @@ -// ignore_for_file: talawa_api_doc -// ignore_for_file: talawa_good_doc_comments - -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:hive/hive.dart'; -import 'package:mockito/mockito.dart'; -import 'package:talawa/router.dart' as router; -import 'package:talawa/services/size_config.dart'; -import 'package:talawa/utils/app_localization.dart'; -import 'package:talawa/utils/queries.dart'; -import 'package:talawa/view_model/lang_view_model.dart'; -import 'package:talawa/view_model/main_screen_view_model.dart'; -import 'package:talawa/view_model/theme_view_model.dart'; -import 'package:talawa/view_model/widgets_view_models/custom_drawer_view_model.dart'; -import 'package:talawa/views/base_view.dart'; -import 'package:talawa/widgets/custom_alert_dialog.dart'; -import 'package:talawa/widgets/custom_drawer.dart'; -import 'package:talawa/widgets/theme_switch.dart'; -import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; - -// import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; - -import '../helpers/test_helpers.dart'; -// import '../helpers/test_helpers.mocks.dart'; -import '../helpers/test_locator.dart'; -import '../model_tests/app_tour_test.dart'; - -Widget createAppTourDialog({bool demoMode = true}) => BaseView( - onModelReady: (model) => model.initialize(), - builder: (context, langModel, child) { - return MaterialApp( - locale: const Locale('en'), - localizationsDelegates: [ - const AppLocalizationsDelegate(isTest: true), - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - home: BaseView( - onModelReady: (model2) => model2.initialise( - context, - fromSignUp: false, - mainScreenIndex: 0, - demoMode: demoMode, - testMode: true, - ), - builder: (context, model2, child) { - model2.context = context; - model2.appTour = MockAppTour(model: model2); - model2.pluginPrototypeData.putIfAbsent( - "Plugin1", - () => { - "pluginName": "Plugin1", - "pluginInstallStatus": true, - 'icon': Icons.abc, - 'class': const ChangeThemeTile(), - }, - ); - model2.fetchAndAddPlugins(context); - return Scaffold( - drawer: CustomDrawer(homeModel: model2), - key: MainScreenViewModel.scaffoldKey, - body: model2.appTourDialog(context), - ); - }, - ), - navigatorKey: navigationService.navigatorKey, - onGenerateRoute: router.generateRoute, - ); - }, - ); - -class MockCallBack extends Mock { - void call(); -} - -class MockBuildContext extends Mock implements BuildContext {} - -MainScreenViewModel getModel() { - final model = MainScreenViewModel(); - model.context = MockBuildContext(); - return model; -} - -void verifyInteraction(dynamic x, {required String mockName}) { - // Ensures that navigation service was called - try { - verifyZeroInteractions(x); - //If 0 interactions passes that means mock was not called hence test fails - throw Exception("Expected interaction but found 0 with $mockName"); - } on TestFailure { - //If test fails then 1 or more interactions with navigation service hence test passes - expect(true, true); - } -} - -void main() async { - final Directory dir = Directory('test/fixtures/core'); - - Hive.init(dir.path); - // ..registerAdapter(UserAdapter()) - // ..registerAdapter(OrgInfoAdapter()); - - // final userBox = await Hive.openBox('currentUser'); - // final urlBox = await Hive.openBox('url'); - // final orgBox = await Hive.openBox('currentOrg'); - final pluginBox = await Hive.openBox('pluginBox'); - - final List> samplePluginData = [ - { - "pluginName": "Plugin1", - "pluginInstallStatus": true, - }, - // Add more sample plugin data as needed - ]; - - // Store the sample data in the 'plugins' key of 'pluginBox' - pluginBox.put('plugins', samplePluginData); - - // No need to change - setUpAll(() { - locator.registerFactory(() => CustomDrawerViewModel()); - locator.registerFactory(() => MainScreenViewModel()); - locator.registerFactory(() => AppTheme()); - locator.registerSingleton(SizeConfig()); - locator.registerFactory(() => Queries()); - locator().test(); - }); - - tearDownAll(() { - locator.unregister(); - File('test/fixtures/core/currentorg.hive').delete(); - File('test/fixtures/core/currentorg.lock').delete(); - File('test/fixtures/core/currentuser.hive').delete(); - File('test/fixtures/core/currentuser.lock').delete(); - File('test/fixtures/core/pluginbox.hive').delete(); - File('test/fixtures/core/pluginbox.lock').delete(); - }); - - group("MainScreen ViewModel Tests - ", () { - test("When initialized current index should be 0", () { - final mainTestModel = getModel(); - expect(mainTestModel.currentPageIndex, 0); - }); - }); - - // May need to change - group("onTabTapped -", () { - test("When an index is passed that, current index should equal that index", - () { - final mainTestModel = getModel(); - mainTestModel.onTabTapped(4); - expect(mainTestModel.currentPageIndex, 4); - }); - - test("When called function should notify listeners of tab change", () { - final mockcallback = MockCallBack(); - final mainTestModel = getModel(); - mainTestModel.addListener(mockcallback); - - mainTestModel.onTabTapped(0); - verify(mockcallback()).called(1); - }); - }); - - group("initialize", () { - final context = MockBuildContext(); - SizeConfig().test(); - setUp(() => registerServices()); - tearDown(() => unregisterServices()); - - void runIntialize({ - required bool fSignUp, - int mainIndex = 1, - required MainScreenViewModel model, - BuildContext? pcontext, - }) { - model.initialise( - pcontext ?? context, - fromSignUp: fSignUp, - mainScreenIndex: mainIndex, - ); - } - - test( - "MainScreenViewModel showAppTour and currentIndex should equal values passed to fromSignUp and mainScreenIndex", - () { - const bool fSignup = true; - const int mainIndex = 1; - final mainTestModel = getModel(); - runIntialize( - fSignUp: fSignup, - mainIndex: mainIndex, - model: mainTestModel, - ); - - expect(mainTestModel.showAppTour, fSignup); - expect(mainTestModel.currentPageIndex, mainIndex); - }); - - test('Test for showHome method', () { - final model = getModel(); - - model.showHome( - TargetFocus( - identify: "keyDrawerLeaveCurrentOrg", - keyTarget: MainScreenViewModel.keyDrawerLeaveCurrentOrg, - ), - ); - }); - - test( - "When fromSignUp is false tourComplete should equal true, tourSkipped and showApptour false", - () { - final mainTestModel = getModel(); - runIntialize(fSignUp: false, model: mainTestModel); - expect(mainTestModel.tourComplete, true); - expect(mainTestModel.tourSkipped, false); - expect(mainTestModel.showAppTour, false); - }); - - test("When fromSignUp is false, App Tour dialog should not be displayed", - () async { - final mocknav = getAndRegisterNavigationService(); - final mainTestModel = getModel(); - - mainTestModel.initialise( - MockBuildContext(), - fromSignUp: false, - mainScreenIndex: 0, - ); - - // Ensures that navigation service was not called - verifyZeroInteractions(mocknav); - }); - - testWidgets('Test for apptour dialog skip action.', (tester) async { - await tester.pumpWidget(createAppTourDialog()); - await tester.pumpAndSettle(const Duration(seconds: 1)); - - expect(find.byType(CustomAlertDialog), findsOneWidget); - - // await tester.pumpAndSettle(); - - final skipBtn = find.textContaining('Skip'); - - expect(skipBtn, findsOneWidget); - - await tester.tap(skipBtn); - await tester.pumpAndSettle( - const Duration(seconds: 1), - ); - }); - - testWidgets('Test for apptour dialog success action.', (tester) async { - await tester.pumpWidget(createAppTourDialog()); - await tester.pumpAndSettle(const Duration(seconds: 1)); - - final mockUserConfig = getAndRegisterUserConfig(); - when(mockUserConfig.loggedIn).thenReturn(true); - - MainScreenViewModel.scaffoldKey.currentState?.openDrawer(); - - expect(find.byType(CustomAlertDialog), findsOneWidget); - - final startBtn = find.textContaining('Start').last; - - expect(startBtn, findsOneWidget); - - await tester.tap(startBtn); - - await tester.pumpAndSettle(const Duration(seconds: 2)); - }); - - testWidgets('Test for fetchAndAddPlugins when not in demoMode', - (tester) async { - final app = createAppTourDialog(demoMode: false); - - await tester.pumpWidget(app); - await tester.pumpAndSettle(const Duration(seconds: 1)); - }); - - testWidgets('Test for tourhomeTargets.', (tester) async { - final model = getAndRegisterUserConfig(); - const val1 = true; - when(model.loggedIn).thenAnswer((_) => val1); - - // locator.registerFactory(() => CustomDrawerViewModel()); - - late final MainScreenViewModel mainScreenModel; - final app = MaterialApp( - builder: (context, child) => BaseView( - builder: (context, model2, child) { - model2.context = context; - model2.testMode = true; - mainScreenModel = model2; - model2.appTour = MockAppTour(model: model2); - model2.currentPageIndex = 0; - return Scaffold( - key: MainScreenViewModel.scaffoldKey, - drawer: CustomDrawer(homeModel: mainScreenModel), - body: TextButton( - onPressed: () { - model2.showHome( - TargetFocus( - identify: "keySHMenuIcon", - keyTarget: model2.keySHMenuIcon, - ), - ); - model2.tourHomeTargets(); - }, - child: const Text('tour home'), - ), - ); - }, - ), - ); - - await tester.pumpWidget(app); - - await tester.pumpAndSettle(const Duration(seconds: 1)); - - expect(find.textContaining('tour home'), findsOneWidget); - - await tester.tap(find.textContaining('tour home')); - - // // ignore: avoid_dynamic_calls - // print(mainScreenModel.targets[1].description); - - // // ignore: avoid_dynamic_calls - // mainScreenModel.targets[5].next!(); - - // verify(navigationService.pop()); - // locator.unregister(); - }); - - // testWidgets('Test for tourhomeTargets.', (tester) async { - // final model = getAndRegisterUserConfig(); - // bool val = false; - // when(model.loggedIn).thenAnswer((_) => val); - - // // locator.registerFactory(() => CustomDrawerViewModel()); - - // late final MainScreenViewModel mainScreenModel; - // final app =BaseView( - // builder: (context, model2, child) { - // model2.context = context; - // model2.testMode = true; - // mainScreenModel = model2; - // model2.currentPageIndex = 0; - // return MaterialApp( - // builder:(context, child) => Scaffold( - // body: Scaffold( - // key: MainScreenViewModel.scaffoldKey, - // drawer: CustomDrawer(homeModel: mainScreenModel), - // body: TextButton(onPressed: () { - // model2.tourHomeTargets(); - // }, child: const Text('tour home')), - // ), - // ) - // ); - // }, - - // ); - - // await tester.pumpWidget(app); - - // await tester.pumpAndSettle(const Duration(seconds: 1)); - - // expect(find.textContaining('tour home'), findsOneWidget); - - // await tester.tap(find.textContaining('tour home')); - - // mainScreenModel.targets[4].next!(); - - // verify(navigationService.pop()); - // }); - - // testWidgets('Test for tourEventTargets.', (tester) async { - // final model = getAndRegisterUserConfig(); - // when(model.loggedIn).thenAnswer((_) => true); - - // final app = BaseView( - // builder: (context, model2, child) { - // model2.context = context; - // model2.testMode = true; - // model2.appTour = MockAppTour(model: model2); - // model2.currentPageIndex = 1; - // return MaterialApp( - // builder: (context, child) => Scaffold( - // body: TextButton( - // onPressed: () { - // model2.tourEventTargets(); - // }, - // child: const Text('tour event targets'), - // ), - // ), - // ); - // }, - // ); - - // await tester.pumpWidget(app); - - // await tester.pumpAndSettle(const Duration(seconds: 1)); - - // expect(find.textContaining('tour event targets'), findsOneWidget); - - // await tester.tap(find.textContaining('tour event targets')); - // }); - - testWidgets('Test for tourChats.', (tester) async { - final model = getAndRegisterUserConfig(); - when(model.loggedIn).thenAnswer((_) => true); - - final app = BaseView( - builder: (context, model2, child) { - model2.context = context; - model2.testMode = true; - model2.appTour = MockAppTour(model: model2); - model2.currentPageIndex = 1; - return MaterialApp( - builder: (context, child) => Scaffold( - body: TextButton( - onPressed: () { - model2.tourChat(); - }, - child: const Text('tour chat targets'), - ), - ), - ); - }, - ); - - await tester.pumpWidget(app); - - await tester.pumpAndSettle(const Duration(seconds: 1)); - - expect(find.textContaining('tour chat targets'), findsOneWidget); - - await tester.tap(find.textContaining('tour chat targets')); - }); - - testWidgets('Test for addPost.', (tester) async { - final model = getAndRegisterUserConfig(); - when(model.loggedIn).thenAnswer((_) => true); - - final app = MaterialApp( - builder: (context, child) => BaseView( - builder: (context, model2, child) { - model2.context = context; - model2.testMode = true; - model2.appTour = MockAppTour(model: model2); - model2.currentPageIndex = 1; - return Scaffold( - body: TextButton( - onPressed: () { - model2.tourAddPost(); - }, - child: const Text('tour add post'), - ), - ); - }, - ), - ); - - await tester.pumpWidget(app); - - await tester.pumpAndSettle(const Duration(seconds: 1)); - - expect(find.textContaining('tour add post'), findsOneWidget); - - await tester.tap(find.textContaining('tour add post')); - }); - - // testWidgets('Test for profile tour.', (tester) async { - // final model = getAndRegisterUserConfig(); - // when(model.loggedIn).thenAnswer((_) => true); - - // final app = BaseView( - // builder: (context, model2, child) { - // model2.context = context; - // model2.testMode = true; - // model2.appTour = MockAppTour(model: model2); - // model2.currentPageIndex = 1; - // return MaterialApp( - // builder: (context, child) => Scaffold( - // body: TextButton( - // onPressed: () { - // model2.tourProfile(); - // }, - // child: const Text('tour profile'), - // ), - // ), - // ); - // }, - // ); - - // await tester.pumpWidget(app); - - // await tester.pumpAndSettle(const Duration(seconds: 1)); - - // expect(find.textContaining('tour profile'), findsOneWidget); - - // await tester.tap(find.textContaining('tour profile')); - - // // print(mockedModel.targets[5].); - // }); - - // testWidgets('Test for focustarget widget.', (tester) async { - // late MainScreenViewModel mockModel = MainScreenViewModel(); - - // model.focusTarget( model.keyBNChat, 'not', 'ok').contents[] - - // Widget app = BaseView( - // onModelReady: (model) => model.initialize(), - // builder: (context, model, child) { - // return MaterialApp( - // locale: const Locale('en'), - // localizationsDelegates: [ - // const AppLocalizationsDelegate(isTest: true), - // GlobalMaterialLocalizations.delegate, - // GlobalWidgetsLocalizations.delegate, - // ], - // theme: Provider.of(context).isdarkTheme - // ? TalawaTheme.darkTheme - // : TalawaTheme.lightTheme, - // home: BaseView( - // onModelReady: (model2) => model2.initialise(context, fromSignUp: false, mainScreenIndex: 0, testMode: true, demoMode: true), - // builder: (context, model2, child) { - // model2.context = context; - // mockModel = model2; - // return Scaffold( - // body: TextButton( - // child: const Text('press me'), - // onPressed: () { - // model2.tourProfile(); - // model2.showTutorial(onClickTarget: (targetFocus) { - // return TargetFocus(); - // }, onFinish: () { - // return TargetFocus(); - // }); - // }, - // ), - // ); - // }, - // ), - // navigatorKey: navigationService.navigatorKey, - // onGenerateRoute: router.generateRoute, - // ); - // }); - - // await tester.pumpWidget(app); - // await tester.pumpAndSettle(); - - // expect(find.text('press me'), findsOneWidget); - - // await tester.tap(find.text('press me')); - // await tester.pumpAndSettle(); - - // print(mockModel.targets); - - // }); - - // testWidgets('Test for fetchAndAddPlugins.', (tester) async { - - // await tester.pumpWidget(createAppTourDialog(demoMode: false,)); - // await tester.pumpAndSettle(const Duration(seconds: 1)); - - // }); - - // test("When fromSignUp is true, App Tour dialog should be displayed", - // () async { - // final mocknav = getAndRegisterNavigationService(); - // final mainTestModel = getModel(); - - // //Waits for any delay in navigation being called - // mainTestModel.initialise( - // mainTestModel.context, - // fromSignUp: true, - // mainScreenIndex: 0, - // ); - - // await Future.delayed(const Duration(seconds: 2)); - - // final captured = verify( - // (navigationService as MockNavigationService).pushDialog(captureAny), - // ).captured; - // captured[0].success(); - // captured[0].secondaryButtonTap(); - - // //Ensures that naviagation service was called - // verifyInteraction(mocknav, mockName: "NavigationService"); - // }); - // }); - - // group("showTutorial", () { - // final mainTestModel = getModel(); - // test("When called tutorial coach should be assigned a value", () { - // mainTestModel.showTutorial( - // onClickTarget: (TargetFocus x) {}, - // onFinish: () {}, - // ); - // expect(mainTestModel.tutorialCoachMark, isNotNull); - - // // mainTestModel.tutorialCoachMark.skip(); - // }); - // }); - - // group("tourHomeTargets", () { - // final mainTestModel = getModel(); - // final TargetFocus testTarget = - // TargetFocus(identify: "TestTarget", keyTarget: mainTestModel.keyBNChat); - // test("target list should be cleared before adding new targets", () { - // //Adding a testtarget before method is called - // mainTestModel.targets.add(testTarget); - // // mainTestModel.context = MockBuildContext(); - // mainTestModel.tourHomeTargets(); - // // targets list should not contain testtarget - // expect(mainTestModel.targets.contains(testTarget), false); - // }); - // }); - - // group("tourEventTargets", () { - // final mainTestModel = getModel(); - // test("target list should be cleared before adding new targets", () { - // final TargetFocus testTarget = TargetFocus( - // identify: "TestTarget", - // keyTarget: mainTestModel.keyBNChat, - // ); - // //Adding a target before method is called - // mainTestModel.targets.add(testTarget); - - // mainTestModel.tourEventTargets(); - // // targets list should not contain target - // expect(mainTestModel.targets.contains(testTarget), false); - // }); - // }); - - // group("tourAddPost", () { - // final mainTestModel = getModel(); - // test("target list should be cleared before adding new targets", () { - // final TargetFocus testTarget = TargetFocus( - // identify: "TestTarget", - // keyTarget: mainTestModel.keyBNChat, - // ); - // //Adding a target before method is called - // mainTestModel.targets.add(testTarget); - - // mainTestModel.tourAddPost(); - // // targets list should not contain target - // expect(mainTestModel.targets.contains(testTarget), false); - // }); - // }); - // group("tourChat", () { - // final mainTestModel = getModel(); - // test("target list should be cleared before adding new targets", () { - // final TargetFocus testTarget = TargetFocus( - // identify: "TestTarget", - // keyTarget: mainTestModel.keyBNChat, - // ); - // //Adding a target before method is called - // mainTestModel.targets.add(testTarget); - - // mainTestModel.tourChat(); - // // targets list should not contain target - // expect(mainTestModel.targets.contains(testTarget), false); - // }); - // }); - - // group("tourProfile", () { - // final mainTestModel = getModel(); - // test("target list should be cleared before adding new targets", () { - // final TargetFocus testTarget = TargetFocus( - // identify: "TestTarget", - // keyTarget: mainTestModel.keyBNChat, - // ); - // //Adding a target before method is called - // mainTestModel.targets.add(testTarget); - - // mainTestModel.tourProfile(); - // // targets list should not contain target - // expect(mainTestModel.targets.contains(testTarget), false); - // }); - }); -} +// ignore_for_file: talawa_api_doc +// ignore_for_file: talawa_good_doc_comments + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:hive/hive.dart'; +import 'package:mockito/mockito.dart'; +import 'package:talawa/router.dart' as router; +import 'package:talawa/services/size_config.dart'; +import 'package:talawa/utils/app_localization.dart'; +import 'package:talawa/utils/queries.dart'; +import 'package:talawa/view_model/lang_view_model.dart'; +import 'package:talawa/view_model/main_screen_view_model.dart'; +import 'package:talawa/view_model/theme_view_model.dart'; +import 'package:talawa/view_model/widgets_view_models/custom_drawer_view_model.dart'; +import 'package:talawa/views/base_view.dart'; +import 'package:talawa/widgets/custom_alert_dialog.dart'; +import 'package:talawa/widgets/custom_drawer.dart'; +import 'package:talawa/widgets/theme_switch.dart'; +import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; + +// import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; + +import '../helpers/test_helpers.dart'; +// import '../helpers/test_helpers.mocks.dart'; +import '../helpers/test_locator.dart'; +import '../model_tests/app_tour_test.dart'; + +Widget createAppTourDialog({bool demoMode = true}) => BaseView( + onModelReady: (model) => model.initialize(), + builder: (context, langModel, child) { + return MaterialApp( + locale: const Locale('en'), + localizationsDelegates: [ + const AppLocalizationsDelegate(isTest: true), + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + home: BaseView( + onModelReady: (model2) => model2.initialise( + context, + fromSignUp: false, + mainScreenIndex: 0, + demoMode: demoMode, + testMode: true, + ), + builder: (context, model2, child) { + model2.context = context; + model2.appTour = MockAppTour(model: model2); + model2.pluginPrototypeData.putIfAbsent( + "Plugin1", + () => { + "pluginName": "Plugin1", + "pluginInstallStatus": true, + 'icon': Icons.abc, + 'class': const ChangeThemeTile(), + }, + ); + model2.fetchAndAddPlugins(context); + return Scaffold( + drawer: CustomDrawer(homeModel: model2), + key: MainScreenViewModel.scaffoldKey, + body: model2.appTourDialog(context), + ); + }, + ), + navigatorKey: navigationService.navigatorKey, + onGenerateRoute: router.generateRoute, + ); + }, + ); + +class MockCallBack extends Mock { + void call(); +} + +class MockBuildContext extends Mock implements BuildContext {} + +MainScreenViewModel getModel() { + final model = MainScreenViewModel(); + model.context = MockBuildContext(); + return model; +} + +void verifyInteraction(dynamic x, {required String mockName}) { + // Ensures that navigation service was called + try { + verifyZeroInteractions(x); + //If 0 interactions passes that means mock was not called hence test fails + throw Exception("Expected interaction but found 0 with $mockName"); + } on TestFailure { + //If test fails then 1 or more interactions with navigation service hence test passes + expect(true, true); + } +} + +void main() async { + final Directory dir = Directory('test/fixtures/core'); + + Hive.init(dir.path); + // ..registerAdapter(UserAdapter()) + // ..registerAdapter(OrgInfoAdapter()); + + // final userBox = await Hive.openBox('currentUser'); + // final urlBox = await Hive.openBox('url'); + // final orgBox = await Hive.openBox('currentOrg'); + final pluginBox = await Hive.openBox('pluginBox'); + + final List> samplePluginData = [ + { + "pluginName": "Plugin1", + "pluginInstallStatus": true, + }, + // Add more sample plugin data as needed + ]; + + // Store the sample data in the 'plugins' key of 'pluginBox' + pluginBox.put('plugins', samplePluginData); + + // No need to change + setUpAll(() { + locator.registerFactory(() => CustomDrawerViewModel()); + locator.registerFactory(() => MainScreenViewModel()); + locator.registerFactory(() => AppTheme()); + locator.registerSingleton(SizeConfig()); + locator.registerFactory(() => Queries()); + locator().test(); + }); + + tearDownAll(() { + locator.unregister(); + File('test/fixtures/core/currentorg.hive').delete(); + File('test/fixtures/core/currentorg.lock').delete(); + File('test/fixtures/core/currentuser.hive').delete(); + File('test/fixtures/core/currentuser.lock').delete(); + File('test/fixtures/core/pluginbox.hive').delete(); + File('test/fixtures/core/pluginbox.lock').delete(); + }); + + group("MainScreen ViewModel Tests - ", () { + test("When initialized current index should be 0", () { + final mainTestModel = getModel(); + expect(mainTestModel.currentPageIndex, 0); + }); + }); + + // May need to change + group("onTabTapped -", () { + test("When an index is passed that, current index should equal that index", + () { + final mainTestModel = getModel(); + mainTestModel.onTabTapped(4); + expect(mainTestModel.currentPageIndex, 4); + }); + + test("When called function should notify listeners of tab change", () { + final mockcallback = MockCallBack(); + final mainTestModel = getModel(); + mainTestModel.addListener(mockcallback); + + mainTestModel.onTabTapped(0); + verify(mockcallback()).called(1); + }); + }); + + group("initialize", () { + final context = MockBuildContext(); + SizeConfig().test(); + setUp(() => registerServices()); + tearDown(() => unregisterServices()); + + void runIntialize({ + required bool fSignUp, + int mainIndex = 1, + required MainScreenViewModel model, + BuildContext? pcontext, + }) { + model.initialise( + pcontext ?? context, + fromSignUp: fSignUp, + mainScreenIndex: mainIndex, + ); + } + + test( + "MainScreenViewModel showAppTour and currentIndex should equal values passed to fromSignUp and mainScreenIndex", + () { + const bool fSignup = true; + const int mainIndex = 1; + final mainTestModel = getModel(); + runIntialize( + fSignUp: fSignup, + mainIndex: mainIndex, + model: mainTestModel, + ); + + expect(mainTestModel.showAppTour, fSignup); + expect(mainTestModel.currentPageIndex, mainIndex); + }); + + test('Test for showHome method', () { + final model = getModel(); + + model.showHome( + TargetFocus( + identify: "keyDrawerLeaveCurrentOrg", + keyTarget: MainScreenViewModel.keyDrawerLeaveCurrentOrg, + ), + ); + }); + + test( + "When fromSignUp is false tourComplete should equal true, tourSkipped and showApptour false", + () { + final mainTestModel = getModel(); + runIntialize(fSignUp: false, model: mainTestModel); + expect(mainTestModel.tourComplete, true); + expect(mainTestModel.tourSkipped, false); + expect(mainTestModel.showAppTour, false); + }); + + test("When fromSignUp is false, App Tour dialog should not be displayed", + () async { + final mocknav = getAndRegisterNavigationService(); + final mainTestModel = getModel(); + + mainTestModel.initialise( + MockBuildContext(), + fromSignUp: false, + mainScreenIndex: 0, + ); + + // Ensures that navigation service was not called + verifyZeroInteractions(mocknav); + }); + + testWidgets('Test for apptour dialog skip action.', (tester) async { + await tester.pumpWidget(createAppTourDialog()); + await tester.pumpAndSettle(const Duration(seconds: 1)); + + expect(find.byType(CustomAlertDialog), findsOneWidget); + + // await tester.pumpAndSettle(); + + final skipBtn = find.textContaining('Skip'); + + expect(skipBtn, findsOneWidget); + + await tester.tap(skipBtn); + await tester.pumpAndSettle( + const Duration(seconds: 1), + ); + }); + + testWidgets('Test for apptour dialog success action.', (tester) async { + await tester.pumpWidget(createAppTourDialog()); + await tester.pumpAndSettle(const Duration(seconds: 1)); + + final mockUserConfig = getAndRegisterUserConfig(); + when(mockUserConfig.loggedIn).thenReturn(true); + + MainScreenViewModel.scaffoldKey.currentState?.openDrawer(); + + expect(find.byType(CustomAlertDialog), findsOneWidget); + + final startBtn = find.textContaining('Start').last; + + expect(startBtn, findsOneWidget); + + await tester.tap(startBtn); + + await tester.pumpAndSettle(const Duration(seconds: 2)); + }); + + testWidgets('Test for fetchAndAddPlugins when not in demoMode', + (tester) async { + final app = createAppTourDialog(demoMode: false); + + await tester.pumpWidget(app); + await tester.pumpAndSettle(const Duration(seconds: 1)); + }); + + testWidgets('Test for tourhomeTargets.', (tester) async { + final model = getAndRegisterUserConfig(); + const val1 = true; + when(model.loggedIn).thenAnswer((_) => val1); + + // locator.registerFactory(() => CustomDrawerViewModel()); + + late final MainScreenViewModel mainScreenModel; + final app = MaterialApp( + builder: (context, child) => BaseView( + builder: (context, model2, child) { + model2.context = context; + model2.testMode = true; + mainScreenModel = model2; + model2.appTour = MockAppTour(model: model2); + model2.currentPageIndex = 0; + return Scaffold( + key: MainScreenViewModel.scaffoldKey, + drawer: CustomDrawer(homeModel: mainScreenModel), + body: TextButton( + onPressed: () { + model2.showHome( + TargetFocus( + identify: "keySHMenuIcon", + keyTarget: model2.keySHMenuIcon, + ), + ); + model2.tourHomeTargets(); + }, + child: const Text('tour home'), + ), + ); + }, + ), + ); + + await tester.pumpWidget(app); + + await tester.pumpAndSettle(const Duration(seconds: 1)); + + expect(find.textContaining('tour home'), findsOneWidget); + + await tester.tap(find.textContaining('tour home')); + + // // ignore: avoid_dynamic_calls + // print(mainScreenModel.targets[1].description); + + // // ignore: avoid_dynamic_calls + // mainScreenModel.targets[5].next!(); + + // verify(navigationService.pop()); + // locator.unregister(); + }); + + // testWidgets('Test for tourhomeTargets.', (tester) async { + // final model = getAndRegisterUserConfig(); + // bool val = false; + // when(model.loggedIn).thenAnswer((_) => val); + + // // locator.registerFactory(() => CustomDrawerViewModel()); + + // late final MainScreenViewModel mainScreenModel; + // final app =BaseView( + // builder: (context, model2, child) { + // model2.context = context; + // model2.testMode = true; + // mainScreenModel = model2; + // model2.currentPageIndex = 0; + // return MaterialApp( + // builder:(context, child) => Scaffold( + // body: Scaffold( + // key: MainScreenViewModel.scaffoldKey, + // drawer: CustomDrawer(homeModel: mainScreenModel), + // body: TextButton(onPressed: () { + // model2.tourHomeTargets(); + // }, child: const Text('tour home')), + // ), + // ) + // ); + // }, + + // ); + + // await tester.pumpWidget(app); + + // await tester.pumpAndSettle(const Duration(seconds: 1)); + + // expect(find.textContaining('tour home'), findsOneWidget); + + // await tester.tap(find.textContaining('tour home')); + + // mainScreenModel.targets[4].next!(); + + // verify(navigationService.pop()); + // }); + + // testWidgets('Test for tourEventTargets.', (tester) async { + // final model = getAndRegisterUserConfig(); + // when(model.loggedIn).thenAnswer((_) => true); + + // final app = BaseView( + // builder: (context, model2, child) { + // model2.context = context; + // model2.testMode = true; + // model2.appTour = MockAppTour(model: model2); + // model2.currentPageIndex = 1; + // return MaterialApp( + // builder: (context, child) => Scaffold( + // body: TextButton( + // onPressed: () { + // model2.tourEventTargets(); + // }, + // child: const Text('tour event targets'), + // ), + // ), + // ); + // }, + // ); + + // await tester.pumpWidget(app); + + // await tester.pumpAndSettle(const Duration(seconds: 1)); + + // expect(find.textContaining('tour event targets'), findsOneWidget); + + // await tester.tap(find.textContaining('tour event targets')); + // }); + + testWidgets('Test for tourChats.', (tester) async { + final model = getAndRegisterUserConfig(); + when(model.loggedIn).thenAnswer((_) => true); + + final app = BaseView( + builder: (context, model2, child) { + model2.context = context; + model2.testMode = true; + model2.appTour = MockAppTour(model: model2); + model2.currentPageIndex = 1; + return MaterialApp( + builder: (context, child) => Scaffold( + body: TextButton( + onPressed: () { + model2.tourChat(); + }, + child: const Text('tour chat targets'), + ), + ), + ); + }, + ); + + await tester.pumpWidget(app); + + await tester.pumpAndSettle(const Duration(seconds: 1)); + + expect(find.textContaining('tour chat targets'), findsOneWidget); + + await tester.tap(find.textContaining('tour chat targets')); + }); + + testWidgets('Test for addPost.', (tester) async { + final model = getAndRegisterUserConfig(); + when(model.loggedIn).thenAnswer((_) => true); + + final app = MaterialApp( + builder: (context, child) => BaseView( + builder: (context, model2, child) { + model2.context = context; + model2.testMode = true; + model2.appTour = MockAppTour(model: model2); + model2.currentPageIndex = 1; + return Scaffold( + body: TextButton( + onPressed: () { + model2.tourAddPost(); + }, + child: const Text('tour add post'), + ), + ); + }, + ), + ); + + await tester.pumpWidget(app); + + await tester.pumpAndSettle(const Duration(seconds: 1)); + + expect(find.textContaining('tour add post'), findsOneWidget); + + await tester.tap(find.textContaining('tour add post')); + }); + + // testWidgets('Test for profile tour.', (tester) async { + // final model = getAndRegisterUserConfig(); + // when(model.loggedIn).thenAnswer((_) => true); + + // final app = BaseView( + // builder: (context, model2, child) { + // model2.context = context; + // model2.testMode = true; + // model2.appTour = MockAppTour(model: model2); + // model2.currentPageIndex = 1; + // return MaterialApp( + // builder: (context, child) => Scaffold( + // body: TextButton( + // onPressed: () { + // model2.tourProfile(); + // }, + // child: const Text('tour profile'), + // ), + // ), + // ); + // }, + // ); + + // await tester.pumpWidget(app); + + // await tester.pumpAndSettle(const Duration(seconds: 1)); + + // expect(find.textContaining('tour profile'), findsOneWidget); + + // await tester.tap(find.textContaining('tour profile')); + + // // print(mockedModel.targets[5].); + // }); + + // testWidgets('Test for focustarget widget.', (tester) async { + // late MainScreenViewModel mockModel = MainScreenViewModel(); + + // model.focusTarget( model.keyBNChat, 'not', 'ok').contents[] + + // Widget app = BaseView( + // onModelReady: (model) => model.initialize(), + // builder: (context, model, child) { + // return MaterialApp( + // locale: const Locale('en'), + // localizationsDelegates: [ + // const AppLocalizationsDelegate(isTest: true), + // GlobalMaterialLocalizations.delegate, + // GlobalWidgetsLocalizations.delegate, + // ], + // theme: Provider.of(context).isdarkTheme + // ? TalawaTheme.darkTheme + // : TalawaTheme.lightTheme, + // home: BaseView( + // onModelReady: (model2) => model2.initialise(context, fromSignUp: false, mainScreenIndex: 0, testMode: true, demoMode: true), + // builder: (context, model2, child) { + // model2.context = context; + // mockModel = model2; + // return Scaffold( + // body: TextButton( + // child: const Text('press me'), + // onPressed: () { + // model2.tourProfile(); + // model2.showTutorial(onClickTarget: (targetFocus) { + // return TargetFocus(); + // }, onFinish: () { + // return TargetFocus(); + // }); + // }, + // ), + // ); + // }, + // ), + // navigatorKey: navigationService.navigatorKey, + // onGenerateRoute: router.generateRoute, + // ); + // }); + + // await tester.pumpWidget(app); + // await tester.pumpAndSettle(); + + // expect(find.text('press me'), findsOneWidget); + + // await tester.tap(find.text('press me')); + // await tester.pumpAndSettle(); + + // print(mockModel.targets); + + // }); + + // testWidgets('Test for fetchAndAddPlugins.', (tester) async { + + // await tester.pumpWidget(createAppTourDialog(demoMode: false,)); + // await tester.pumpAndSettle(const Duration(seconds: 1)); + + // }); + + // test("When fromSignUp is true, App Tour dialog should be displayed", + // () async { + // final mocknav = getAndRegisterNavigationService(); + // final mainTestModel = getModel(); + + // //Waits for any delay in navigation being called + // mainTestModel.initialise( + // mainTestModel.context, + // fromSignUp: true, + // mainScreenIndex: 0, + // ); + + // await Future.delayed(const Duration(seconds: 2)); + + // final captured = verify( + // (navigationService as MockNavigationService).pushDialog(captureAny), + // ).captured; + // captured[0].success(); + // captured[0].secondaryButtonTap(); + + // //Ensures that naviagation service was called + // verifyInteraction(mocknav, mockName: "NavigationService"); + // }); + // }); + + // group("showTutorial", () { + // final mainTestModel = getModel(); + // test("When called tutorial coach should be assigned a value", () { + // mainTestModel.showTutorial( + // onClickTarget: (TargetFocus x) {}, + // onFinish: () {}, + // ); + // expect(mainTestModel.tutorialCoachMark, isNotNull); + + // // mainTestModel.tutorialCoachMark.skip(); + // }); + // }); + + // group("tourHomeTargets", () { + // final mainTestModel = getModel(); + // final TargetFocus testTarget = + // TargetFocus(identify: "TestTarget", keyTarget: mainTestModel.keyBNChat); + // test("target list should be cleared before adding new targets", () { + // //Adding a testtarget before method is called + // mainTestModel.targets.add(testTarget); + // // mainTestModel.context = MockBuildContext(); + // mainTestModel.tourHomeTargets(); + // // targets list should not contain testtarget + // expect(mainTestModel.targets.contains(testTarget), false); + // }); + // }); + + // group("tourEventTargets", () { + // final mainTestModel = getModel(); + // test("target list should be cleared before adding new targets", () { + // final TargetFocus testTarget = TargetFocus( + // identify: "TestTarget", + // keyTarget: mainTestModel.keyBNChat, + // ); + // //Adding a target before method is called + // mainTestModel.targets.add(testTarget); + + // mainTestModel.tourEventTargets(); + // // targets list should not contain target + // expect(mainTestModel.targets.contains(testTarget), false); + // }); + // }); + + // group("tourAddPost", () { + // final mainTestModel = getModel(); + // test("target list should be cleared before adding new targets", () { + // final TargetFocus testTarget = TargetFocus( + // identify: "TestTarget", + // keyTarget: mainTestModel.keyBNChat, + // ); + // //Adding a target before method is called + // mainTestModel.targets.add(testTarget); + + // mainTestModel.tourAddPost(); + // // targets list should not contain target + // expect(mainTestModel.targets.contains(testTarget), false); + // }); + // }); + // group("tourChat", () { + // final mainTestModel = getModel(); + // test("target list should be cleared before adding new targets", () { + // final TargetFocus testTarget = TargetFocus( + // identify: "TestTarget", + // keyTarget: mainTestModel.keyBNChat, + // ); + // //Adding a target before method is called + // mainTestModel.targets.add(testTarget); + + // mainTestModel.tourChat(); + // // targets list should not contain target + // expect(mainTestModel.targets.contains(testTarget), false); + // }); + // }); + + // group("tourProfile", () { + // final mainTestModel = getModel(); + // test("target list should be cleared before adding new targets", () { + // final TargetFocus testTarget = TargetFocus( + // identify: "TestTarget", + // keyTarget: mainTestModel.keyBNChat, + // ); + // //Adding a target before method is called + // mainTestModel.targets.add(testTarget); + + // mainTestModel.tourProfile(); + // // targets list should not contain target + // expect(mainTestModel.targets.contains(testTarget), false); + // }); + }); +} diff --git a/test/widget_tests/after_auth_screens/add_post_page_test.dart b/test/views/after_auth_screens/add_post_page_test.dart similarity index 99% rename from test/widget_tests/after_auth_screens/add_post_page_test.dart rename to test/views/after_auth_screens/add_post_page_test.dart index 2d6d3c9e1c..73644edea8 100644 --- a/test/widget_tests/after_auth_screens/add_post_page_test.dart +++ b/test/views/after_auth_screens/add_post_page_test.dart @@ -75,6 +75,7 @@ Widget createAddPostScreen({ const AppLocalizationsDelegate(isTest: true), GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, ], home: Scaffold( /// MainScreenViewModel.scaffoldKey.currentState will return null diff --git a/test/widget_tests/after_auth_screens/events/create_event_form_test.dart b/test/widget_tests/after_auth_screens/events/create_event_form_test.dart index 63bb107fde..f74e0754d9 100644 --- a/test/widget_tests/after_auth_screens/events/create_event_form_test.dart +++ b/test/widget_tests/after_auth_screens/events/create_event_form_test.dart @@ -85,94 +85,95 @@ void main() { unregisterViewModels(); unregisterServices(); }); - - testWidgets("Test if create event form shows up", - (WidgetTester tester) async { - await tester.runAsync(() async { - await tester.pumpWidget(createCreateEventForm()); - await tester.pump(); - expect(find.byType(TextFormField), findsNWidgets(3)); - expect( - find.descendant( - of: find.byType(Form), - matching: find.byType(TextFormField), - ), - findsNWidgets(3), - ); + group('Testing create event form', () { + testWidgets("Test if create event form shows up", + (WidgetTester tester) async { + await tester.runAsync(() async { + await tester.pumpWidget(createCreateEventForm()); + await tester.pump(); + expect(find.byType(TextFormField), findsNWidgets(3)); + expect( + find.descendant( + of: find.byType(Form), + matching: find.byType(TextFormField), + ), + findsNWidgets(3), + ); + }); }); - }); - testWidgets("Test if create event key are working", - (WidgetTester tester) async { - await tester.runAsync(() async { - await tester.pumpWidget(createCreateEventForm()); - await tester.pump(); - expect(find.byKey(const Key('create_event_form_tff1')), findsOneWidget); - expect(find.byKey(const Key('create_event_form_tff2')), findsOneWidget); - expect(find.byKey(const Key('create_event_form_tff3')), findsOneWidget); + testWidgets("Test if create event key are working", + (WidgetTester tester) async { + await tester.runAsync(() async { + await tester.pumpWidget(createCreateEventForm()); + await tester.pump(); + expect(find.byKey(const Key('create_event_form_tff1')), findsOneWidget); + expect(find.byKey(const Key('create_event_form_tff2')), findsOneWidget); + expect(find.byKey(const Key('create_event_form_tff3')), findsOneWidget); + }); }); - }); - testWidgets("Test if gesture detector is working", - (WidgetTester tester) async { - await tester.runAsync(() async { - await tester.pumpWidget(createCreateEventForm()); - await tester.pump(); - final gestureDetector = find.byKey(const Key('gesture_cef_test')); - await tester.tap(gestureDetector); - await tester.pump(); - expect(find.byKey(const Key('gesture_cef_test')), findsOneWidget); - await tester.pumpAndSettle(const Duration(milliseconds: 1000)); + testWidgets("Test if gesture detector is working", + (WidgetTester tester) async { + await tester.runAsync(() async { + await tester.pumpWidget(createCreateEventForm()); + await tester.pump(); + final gestureDetector = find.byKey(const Key('gesture_cef_test')); + await tester.tap(gestureDetector); + await tester.pump(); + expect(find.byKey(const Key('gesture_cef_test')), findsOneWidget); + await tester.pumpAndSettle(const Duration(milliseconds: 1000)); + }); }); - }); //--------------------------------------------------- - testWidgets( - 'Test if form of 1st TextField is submitted on pressing enter on mobile keyboard.', - (tester) async { - await tester.runAsync(() async { - await tester.pumpWidget(createCreateEventForm()); - await tester.pump(); + testWidgets( + 'Test if form of 1st TextField is submitted on pressing enter on mobile keyboard.', + (tester) async { + await tester.runAsync(() async { + await tester.pumpWidget(createCreateEventForm()); + await tester.pump(); - await tester.enterText( - find.byKey(const Key('create_event_form_tff1')), - 'fakeEventTitle', - ); - await tester.pump(); - await tester.testTextInput.receiveAction(TextInputAction.next); - await tester.pump(); + await tester.enterText( + find.byKey(const Key('create_event_form_tff1')), + 'fakeEventTitle', + ); + await tester.pump(); + await tester.testTextInput.receiveAction(TextInputAction.next); + await tester.pump(); + }); }); - }); - testWidgets( - 'Test if form of 2nd TextField is submitted on pressing enter on mobile keyboard.', - (tester) async { - await tester.runAsync(() async { - await tester.pumpWidget(createCreateEventForm()); - await tester.pump(); + testWidgets( + 'Test if form of 2nd TextField is submitted on pressing enter on mobile keyboard.', + (tester) async { + await tester.runAsync(() async { + await tester.pumpWidget(createCreateEventForm()); + await tester.pump(); - await tester.enterText( - find.byKey(const Key('create_event_form_tff2')), - 'fakeEventTitle', - ); - await tester.pump(); - await tester.testTextInput.receiveAction(TextInputAction.next); - await tester.pump(); + await tester.enterText( + find.byKey(const Key('create_event_form_tff2')), + 'fakeEventTitle', + ); + await tester.pump(); + await tester.testTextInput.receiveAction(TextInputAction.next); + await tester.pump(); + }); }); - }); - testWidgets( - 'Test if form of 3rd TextField is submitted on pressing enter on mobile keyboard.', - (tester) async { - await tester.runAsync(() async { - await tester.pumpWidget(createCreateEventForm()); - await tester.pump(); + testWidgets( + 'Test if form of 3rd TextField is submitted on pressing enter on mobile keyboard.', + (tester) async { + await tester.runAsync(() async { + await tester.pumpWidget(createCreateEventForm()); + await tester.pump(); - await tester.enterText( - find.byKey(const Key('create_event_form_tff3')), - 'fakeEventTitle', - ); - await tester.pump(); - await tester.testTextInput.receiveAction(TextInputAction.next); - await tester.pump(); + await tester.enterText( + find.byKey(const Key('create_event_form_tff3')), + 'fakeEventTitle', + ); + await tester.pump(); + await tester.testTextInput.receiveAction(TextInputAction.next); + await tester.pump(); + }); }); }); }