merge main
This commit is contained in:
@@ -49,7 +49,6 @@ dart_code_metrics:
|
||||
# Common
|
||||
- avoid-accessing-collections-by-constant-index
|
||||
- avoid-accessing-other-classes-private-members
|
||||
- avoid-async-call-in-sync-function
|
||||
- avoid-cascade-after-if-null
|
||||
- avoid-collapsible-if
|
||||
- avoid-collection-methods-with-unrelated-types
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Afegeix usuaris",
|
||||
"all_people_page_title": "Persones",
|
||||
"all_videos_page_title": "Vídeos",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "No s'ha trobat res arxivat",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Configuració de la memòria cau",
|
||||
"change_password_form_confirm_password": "Confirma la contrasenya",
|
||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_new_password": "New Password",
|
||||
"change_password_form_password_mismatch": "Passwords do not match",
|
||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Místní úložiště",
|
||||
"cache_settings_title": "Nastavení vyrovnávací paměti",
|
||||
"change_password_form_confirm_password": "Potvrďte heslo",
|
||||
"change_password_form_description": "Dobrý den, {firstName} {lastName},\n\nje to buď poprvé, co se přihlašujete do systému, nebo byl vytvořen požadavek na změnu hesla. Níže zadejte nové heslo.",
|
||||
"change_password_form_description": "Dobrý den, {name},\n\nje to buď poprvé, co se přihlašujete do systému, nebo byl vytvořen požadavek na změnu hesla. Níže zadejte nové heslo.",
|
||||
"change_password_form_new_password": "Nové heslo",
|
||||
"change_password_form_password_mismatch": "Hesla se neshodují",
|
||||
"change_password_form_reenter_new_password": "Znovu zadejte nové heslo",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Tilføj brugere",
|
||||
"all_people_page_title": "Personer",
|
||||
"all_videos_page_title": "Videoer",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "Ingen arkiverede elementer blev fundet",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Cache-indstillinger",
|
||||
"change_password_form_confirm_password": "Bekræft kodeord",
|
||||
"change_password_form_description": "Hej {firstName} {lastName},\n\nDette er enten første gang du logger ind eller også er der lavet en anmodning om at ændre dit kodeord. Indtast venligst et nyt kodeord nedenfor.",
|
||||
"change_password_form_description": "Hej {name},\n\nDette er enten første gang du logger ind eller også er der lavet en anmodning om at ændre dit kodeord. Indtast venligst et nyt kodeord nedenfor.",
|
||||
"change_password_form_new_password": "Nyt kodeord",
|
||||
"change_password_form_password_mismatch": "Kodeord er ikke ens",
|
||||
"change_password_form_reenter_new_password": "Gentag nyt kodeord",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Lokaler Speicher",
|
||||
"cache_settings_title": "Zwischenspeicher Einstellungen",
|
||||
"change_password_form_confirm_password": "Passwort bestätigen",
|
||||
"change_password_form_description": "Hallo {firstName} {lastName}\n\nDas ist entweder das erste Mal dass du dich einloggst oder eine Anfrage zur Änderung deines Passwortes wurde gestellt. Bitte gebe das neue Passwort ein.",
|
||||
"change_password_form_description": "Hallo {name}\n\nDas ist entweder das erste Mal dass du dich einloggst oder eine Anfrage zur Änderung deines Passwortes wurde gestellt. Bitte gebe das neue Passwort ein.",
|
||||
"change_password_form_new_password": "Neues Passwort",
|
||||
"change_password_form_password_mismatch": "Passwörter stimmen nicht überein",
|
||||
"change_password_form_reenter_new_password": "Passwort erneut eingeben",
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"album_viewer_page_share_add_users": "Add users",
|
||||
"all_people_page_title": "People",
|
||||
"all_videos_page_title": "Videos",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "No archived assets found",
|
||||
@@ -123,7 +123,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"change_password_form_confirm_password": "Confirm Password",
|
||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_new_password": "New Password",
|
||||
"change_password_form_password_mismatch": "Passwords do not match",
|
||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||
@@ -390,6 +390,28 @@
|
||||
"shared_link_edit_show_meta": "Show metadata",
|
||||
"shared_link_edit_submit_button": "Update link",
|
||||
"shared_link_empty": "You don't have any shared links",
|
||||
"shared_link_error_server_url_fetch": "Cannot fetch the server url",
|
||||
"shared_link_expired": "Expired",
|
||||
"shared_link_expires_days": {
|
||||
"one": "Expires in {} day",
|
||||
"other": "Expires in {} days"
|
||||
},
|
||||
"shared_link_expires_hours": {
|
||||
"one": "Expires in {} hour",
|
||||
"other": "Expires in {} hours"
|
||||
},
|
||||
"shared_link_expires_minutes": {
|
||||
"one": "Expires in {} minute",
|
||||
"other": "Expires in {} minutes"
|
||||
},
|
||||
"shared_link_expires_seconds": {
|
||||
"one": "Expires in {} second",
|
||||
"other": "Expires in {} seconds"
|
||||
},
|
||||
"shared_link_expires_never": "Expires ∞",
|
||||
"shared_link_info_chip_download": "Download",
|
||||
"shared_link_info_chip_metadata": "EXIF",
|
||||
"shared_link_info_chip_upload": "Upload",
|
||||
"shared_link_manage_links": "Manage Shared links",
|
||||
"share_done": "Done",
|
||||
"share_invite": "Invite to album",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Almacenamiento local",
|
||||
"cache_settings_title": "Configuración de la caché",
|
||||
"change_password_form_confirm_password": "Confirmar Contraseña",
|
||||
"change_password_form_description": "Hola {firstName} {lastName},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.",
|
||||
"change_password_form_description": "Hola {name},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.",
|
||||
"change_password_form_new_password": "Nueva Contraseña",
|
||||
"change_password_form_password_mismatch": "Las contraseñas no coinciden",
|
||||
"change_password_form_reenter_new_password": "Vuelve a ingresar la nueva contraseña",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Almacenamiento local",
|
||||
"cache_settings_title": "Configuración de la caché",
|
||||
"change_password_form_confirm_password": "Confirmar Contraseña",
|
||||
"change_password_form_description": "Hola {firstName} {lastName},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.",
|
||||
"change_password_form_description": "Hola {name},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.",
|
||||
"change_password_form_new_password": "Nueva Contraseña",
|
||||
"change_password_form_password_mismatch": "Las contraseñas no coinciden",
|
||||
"change_password_form_reenter_new_password": "Vuelve a ingresar la nueva contraseña",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Almacenamiento local",
|
||||
"cache_settings_title": "Configuración de la caché",
|
||||
"change_password_form_confirm_password": "Confirmar Contraseña",
|
||||
"change_password_form_description": "Hola {firstName} {lastName},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.",
|
||||
"change_password_form_description": "Hola {name},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.",
|
||||
"change_password_form_new_password": "Nueva Contraseña",
|
||||
"change_password_form_password_mismatch": "Las contraseñas no coinciden",
|
||||
"change_password_form_reenter_new_password": "Vuelve a ingresar la nueva contraseña",
|
||||
|
||||
@@ -390,6 +390,28 @@
|
||||
"shared_link_edit_show_meta": "Mostrar metadatos",
|
||||
"shared_link_edit_submit_button": "Actualizar enlace",
|
||||
"shared_link_empty": "No tienes ningún enlace compartido",
|
||||
"shared_link_error_server_url_fetch": "No se puede obtener la URL del servidor",
|
||||
"shared_link_expired": "Expirado",
|
||||
"shared_link_expires_days": {
|
||||
"one": "Expira en {} día",
|
||||
"other": "Expira en {} días"
|
||||
},
|
||||
"shared_link_expires_hours": {
|
||||
"one": "Expira en {} hora",
|
||||
"other": "Expira en {} horas"
|
||||
},
|
||||
"shared_link_expires_minutes": {
|
||||
"one": "Expira en {} minuto",
|
||||
"other": "Expira en {} minutos"
|
||||
},
|
||||
"shared_link_expires_seconds": {
|
||||
"one": "Expira en {} segundo",
|
||||
"other": "Expira en {} segundos"
|
||||
},
|
||||
"shared_link_expires_never": "Sin expiración",
|
||||
"shared_link_info_chip_download": "Descargar",
|
||||
"shared_link_info_chip_metadata": "EXIF",
|
||||
"shared_link_info_chip_upload": "Subir",
|
||||
"shared_link_manage_links": "Administrar enlaces compartidos",
|
||||
"share_done": "Hecho",
|
||||
"share_invite": "Invitar al álbum",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Paikallinen tallennustila",
|
||||
"cache_settings_title": "Välimuistin asetukset",
|
||||
"change_password_form_confirm_password": "Vahvista salasana",
|
||||
"change_password_form_description": "Hei {firstName} {lastName},\n\nTämä on joko ensimmäinen kirjautumisesi järjestelmään tai salasanan vaihtaminen vaihtaminen on pakotettu. Ole hyvä ja syötä uusi salasana alle.",
|
||||
"change_password_form_description": "Hei {name},\n\nTämä on joko ensimmäinen kirjautumisesi järjestelmään tai salasanan vaihtaminen vaihtaminen on pakotettu. Ole hyvä ja syötä uusi salasana alle.",
|
||||
"change_password_form_new_password": "Uusi salasana",
|
||||
"change_password_form_password_mismatch": "Salasanat eivät täsmää",
|
||||
"change_password_form_reenter_new_password": "Uusi salasana uudelleen",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Stockage local",
|
||||
"cache_settings_title": "Paramètres de mise en cache",
|
||||
"change_password_form_confirm_password": "Confirmez le mot de passe",
|
||||
"change_password_form_description": "Bonjour {firstName} {lastName},\n\nC'est la première fois que vous vous connectez au système ou vous avez demandé de changer votre mot de passe. Veuillez saisir le nouveau mot de passe ci-dessous.",
|
||||
"change_password_form_description": "Bonjour {name},\n\nC'est la première fois que vous vous connectez au système ou vous avez demandé de changer votre mot de passe. Veuillez saisir le nouveau mot de passe ci-dessous.",
|
||||
"change_password_form_new_password": "Nouveau mot de passe",
|
||||
"change_password_form_password_mismatch": "Les mots de passe ne correspondent pas",
|
||||
"change_password_form_reenter_new_password": "Saisissez à nouveau le nouveau mot de passe",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Stockage local",
|
||||
"cache_settings_title": "Paramètres de mise en cache",
|
||||
"change_password_form_confirm_password": "Confirmez le mot de passe",
|
||||
"change_password_form_description": "Bonjour {firstName} {lastName},\n\nC'est la première fois que vous vous connectez au système ou vous avez demandé à changer votre mot de passe. Veuillez saisir le nouveau mot de passe ci-dessous.",
|
||||
"change_password_form_description": "Bonjour {name},\n\nC'est la première fois que vous vous connectez au système ou vous avez demandé à changer votre mot de passe. Veuillez saisir le nouveau mot de passe ci-dessous.",
|
||||
"change_password_form_new_password": "Nouveau mot de passe",
|
||||
"change_password_form_password_mismatch": "Les mots de passe ne correspondent pas",
|
||||
"change_password_form_reenter_new_password": "Saisissez à nouveau le nouveau mot de passe",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Add users",
|
||||
"all_people_page_title": "People",
|
||||
"all_videos_page_title": "Videos",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "No archived assets found",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"change_password_form_confirm_password": "Confirm Password",
|
||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_new_password": "New Password",
|
||||
"change_password_form_password_mismatch": "Passwords do not match",
|
||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Felhasználók hozzáadása",
|
||||
"all_people_page_title": "Emberek",
|
||||
"all_videos_page_title": "Videók",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "Nem található archivált média",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Aggiungi utenti",
|
||||
"all_people_page_title": "Persone",
|
||||
"all_videos_page_title": "Video",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "Nessuna oggetto archiviato",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Impostazioni della Cache",
|
||||
"change_password_form_confirm_password": "Conferma Password ",
|
||||
"change_password_form_description": "Ciao {firstName} {lastName},\n\nQuesto è la prima volta che accedi al sistema oppure è stato fatto una richiesta di cambiare la password. Per favore inserisca la nuova password qui sotto",
|
||||
"change_password_form_description": "Ciao {name},\n\nQuesto è la prima volta che accedi al sistema oppure è stato fatto una richiesta di cambiare la password. Per favore inserisca la nuova password qui sotto",
|
||||
"change_password_form_new_password": "Nuova Password",
|
||||
"change_password_form_password_mismatch": "Le password non coincidono",
|
||||
"change_password_form_reenter_new_password": "Inserisci ancora la nuova password ",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "로컬 저장소",
|
||||
"cache_settings_title": "캐시 설정",
|
||||
"change_password_form_confirm_password": "비밀번호 확인",
|
||||
"change_password_form_description": "{firstName} {lastName} 님, 안녕하세요.\n\n시스템에 처음 로그인했거나 비밀번호 변경 요청이 있었습니다. 아래에 새 비밀번호를 입력하세요.",
|
||||
"change_password_form_description": "{name} 님, 안녕하세요.\n\n시스템에 처음 로그인했거나 비밀번호 변경 요청이 있었습니다. 아래에 새 비밀번호를 입력하세요.",
|
||||
"change_password_form_new_password": "새 비밀번호",
|
||||
"change_password_form_password_mismatch": "비밀번호가 일치하지 않습니다",
|
||||
"change_password_form_reenter_new_password": "새 비밀번호 재입력",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Pievienot lietotājus",
|
||||
"all_people_page_title": "Cilvēki",
|
||||
"all_videos_page_title": "Videoklipi",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "Nav atrasts neviens arhivēts aktīvs",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Kešdarbes iestatījumi",
|
||||
"change_password_form_confirm_password": "Apstiprināt Paroli",
|
||||
"change_password_form_description": "Sveiki {FirstName} {LastName},\n\nŠī ir pirmā reize, kad pierakstāties sistēmā, vai arī ir iesniegts pieprasījums mainīt paroli. Lūdzu, zemāk ievadiet jauno paroli.",
|
||||
"change_password_form_description": "Sveiki {name},\n\nŠī ir pirmā reize, kad pierakstāties sistēmā, vai arī ir iesniegts pieprasījums mainīt paroli. Lūdzu, zemāk ievadiet jauno paroli.",
|
||||
"change_password_form_new_password": "Jauna Parole",
|
||||
"change_password_form_password_mismatch": "Paroles nesakrīt",
|
||||
"change_password_form_reenter_new_password": "Atkārtoti ievadīt jaunu paroli",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Add users",
|
||||
"all_people_page_title": "People",
|
||||
"all_videos_page_title": "Videos",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "No archived assets found",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"change_password_form_confirm_password": "Confirm Password",
|
||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_new_password": "New Password",
|
||||
"change_password_form_password_mismatch": "Passwords do not match",
|
||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Lokal lagring",
|
||||
"cache_settings_title": "Bufringsinnstillinger",
|
||||
"change_password_form_confirm_password": "Bekreft passord",
|
||||
"change_password_form_description": "Hei {firstName} {lastName}!\n\nDette er enten første gang du logger på systemet, eller det er sendt en forespørsel om å endre passordet ditt. Vennligst skriv inn det nye passordet nedenfor.",
|
||||
"change_password_form_description": "Hei {name}!\n\nDette er enten første gang du logger på systemet, eller det er sendt en forespørsel om å endre passordet ditt. Vennligst skriv inn det nye passordet nedenfor.",
|
||||
"change_password_form_new_password": "Nytt passord",
|
||||
"change_password_form_password_mismatch": "Passordene stemmer ikke",
|
||||
"change_password_form_reenter_new_password": "Skriv nytt passord igjen",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Gebruikers toevoegen",
|
||||
"all_people_page_title": "Personen",
|
||||
"all_videos_page_title": "Video's",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "Geen gearchiveerde items gevonden",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Cache-instellingen",
|
||||
"change_password_form_confirm_password": "Bevestig wachtwoord",
|
||||
"change_password_form_description": "Hallo {firstName} {lastName},\n\nDit is ofwel de eerste keer dat je inlogt, of er is een verzoek gedaan om je wachtwoord te wijzigen. Vul hieronder een nieuw wachtwoord in.",
|
||||
"change_password_form_description": "Hallo {name},\n\nDit is ofwel de eerste keer dat je inlogt, of er is een verzoek gedaan om je wachtwoord te wijzigen. Vul hieronder een nieuw wachtwoord in.",
|
||||
"change_password_form_new_password": "Nieuw wachtwoord",
|
||||
"change_password_form_password_mismatch": "Wachtwoorden komen niet overeen",
|
||||
"change_password_form_reenter_new_password": "Vul het wachtwoord opnieuw in",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Lokalny magazyn",
|
||||
"cache_settings_title": "Ustawienia Buforowania",
|
||||
"change_password_form_confirm_password": "Potwierdź Hasło",
|
||||
"change_password_form_description": "Cześć {firstName} {lastName},\n\nPierwszy raz logujesz się do systemu, albo złożono prośbę o zmianę hasła. Wpisz poniżej nowe hasło.",
|
||||
"change_password_form_description": "Cześć {name},\n\nPierwszy raz logujesz się do systemu, albo złożono prośbę o zmianę hasła. Wpisz poniżej nowe hasło.",
|
||||
"change_password_form_new_password": "Nowe Hasło",
|
||||
"change_password_form_password_mismatch": "Hasła nie są zgodne",
|
||||
"change_password_form_reenter_new_password": "Wprowadź ponownie Nowe Hasło",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Локальное хранилище",
|
||||
"cache_settings_title": "Настройки кэширования",
|
||||
"change_password_form_confirm_password": "Подтвердите пароль",
|
||||
"change_password_form_description": "Привет {firstName} {lastName},\n\nЭто либо ваш первый вход в систему, либо был сделан запрос на смену пароля. Пожалуйста, введите новый пароль ниже.",
|
||||
"change_password_form_description": "Привет {name},\n\nЭто либо ваш первый вход в систему, либо был сделан запрос на смену пароля. Пожалуйста, введите новый пароль ниже.",
|
||||
"change_password_form_new_password": "Новый пароль",
|
||||
"change_password_form_password_mismatch": "Пароли не совпадают",
|
||||
"change_password_form_reenter_new_password": "Повторно введите новый пароль",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Lokálne úložisko",
|
||||
"cache_settings_title": "Nastavenia vyrovnávacej pamäte",
|
||||
"change_password_form_confirm_password": "Potvrďte heslo",
|
||||
"change_password_form_description": "Dobrý deň, {firstName} {lastName},\n\nBuď sa do systému prihlasujete prvýkrát, alebo bola podaná žiadosť o zmenu hesla. Prosím, zadajte nové heslo nižšie.",
|
||||
"change_password_form_description": "Dobrý deň, {name},\n\nBuď sa do systému prihlasujete prvýkrát, alebo bola podaná žiadosť o zmenu hesla. Prosím, zadajte nové heslo nižšie.",
|
||||
"change_password_form_new_password": "Nové heslo",
|
||||
"change_password_form_password_mismatch": "Heslá sa nezhodujú",
|
||||
"change_password_form_reenter_new_password": "Znova zadajte nové heslo",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Add users",
|
||||
"all_people_page_title": "People",
|
||||
"all_videos_page_title": "Videos",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "No archived assets found",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"change_password_form_confirm_password": "Confirm Password",
|
||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_new_password": "New Password",
|
||||
"change_password_form_password_mismatch": "Passwords do not match",
|
||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Dodaj korisnike",
|
||||
"all_people_page_title": "People",
|
||||
"all_videos_page_title": "Videos",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "No archived assets found",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Add users",
|
||||
"all_people_page_title": "People",
|
||||
"all_videos_page_title": "Videos",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "No archived assets found",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"change_password_form_confirm_password": "Confirm Password",
|
||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_new_password": "New Password",
|
||||
"change_password_form_password_mismatch": "Passwords do not match",
|
||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Lägg till användare",
|
||||
"all_people_page_title": "People",
|
||||
"all_videos_page_title": "Videos",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "No archived assets found",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Cache Inställningar",
|
||||
"change_password_form_confirm_password": "Bekräfta lösenord",
|
||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_new_password": "Nytt lösenord",
|
||||
"change_password_form_password_mismatch": "Passwords do not match",
|
||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "เพิ่มผู้ใช้งาน",
|
||||
"all_people_page_title": "ผู้คน",
|
||||
"all_videos_page_title": "วิดีโอ",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "ไม่พบทรัพยากรในที่เก็บถาวร",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "ตั้งค่าแคช",
|
||||
"change_password_form_confirm_password": "ยืนยันรหัสผ่าน",
|
||||
"change_password_form_description": "สวัสดี {firstName} {lastName},\n\nครั้งนี้อาจจะเป็นครั้งแรกที่คุณเข้าสู่ระบบ หรือมีคำขอเพื่อที่จะเปลี่ยนรหัสผ่านของคุI กรุณาเพิ่มรหัสผ่านใหม่ข้างล่าง",
|
||||
"change_password_form_description": "สวัสดี {name},\n\nครั้งนี้อาจจะเป็นครั้งแรกที่คุณเข้าสู่ระบบ หรือมีคำขอเพื่อที่จะเปลี่ยนรหัสผ่านของคุI กรุณาเพิ่มรหัสผ่านใหม่ข้างล่าง",
|
||||
"change_password_form_new_password": "รหัสผ่านใหม่",
|
||||
"change_password_form_password_mismatch": "รหัสผ่านไม่ตรงกัน",
|
||||
"change_password_form_reenter_new_password": "กรอกรหัสผ่านใหม่",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"album_viewer_page_share_add_users": "Додати користувачів",
|
||||
"all_people_page_title": "Люди",
|
||||
"all_videos_page_title": "Відео",
|
||||
"app_bar_signout_dialog_content": "Are you sure you wanna sign out?",
|
||||
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
|
||||
"app_bar_signout_dialog_ok": "Yes",
|
||||
"app_bar_signout_dialog_title": "Sign out",
|
||||
"archive_page_no_archived_assets": "Немає архівних елементів",
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Local Storage",
|
||||
"cache_settings_title": "Налаштування Кешування",
|
||||
"change_password_form_confirm_password": "Підтвердити пароль",
|
||||
"change_password_form_description": "Привіт {firstName} {lastName},\n\nВи або або вперше входите у систему, або було зроблено запит на зміну вашого пароля. \nВведіть ваш новий пароль.",
|
||||
"change_password_form_description": "Привіт {name},\n\nВи або або вперше входите у систему, або було зроблено запит на зміну вашого пароля. \nВведіть ваш новий пароль.",
|
||||
"change_password_form_new_password": "Новий Пароль",
|
||||
"change_password_form_password_mismatch": "Паролі не співпадають",
|
||||
"change_password_form_reenter_new_password": "Повторіть Новий Пароль",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "Lưu trữ cục bộ",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"change_password_form_confirm_password": "Confirm Password",
|
||||
"change_password_form_description": "Hi {firstName} {lastName},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
|
||||
"change_password_form_new_password": "New Password",
|
||||
"change_password_form_password_mismatch": "Passwords do not match",
|
||||
"change_password_form_reenter_new_password": "Re-enter New Password",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "本地存储",
|
||||
"cache_settings_title": "缓存设置",
|
||||
"change_password_form_confirm_password": "确认密码",
|
||||
"change_password_form_description": "{firstName} {lastName} 您好,\n\n这是您首次登录系统,或被管理员要求更改密码。\n请在下方输入新密码。",
|
||||
"change_password_form_description": "{name} 您好,\n\n这是您首次登录系统,或被管理员要求更改密码。\n请在下方输入新密码。",
|
||||
"change_password_form_new_password": "新密码",
|
||||
"change_password_form_password_mismatch": "密码不匹配",
|
||||
"change_password_form_reenter_new_password": "重新输入新的密码",
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
"cache_settings_tile_title": "本地存储",
|
||||
"cache_settings_title": "缓存设置",
|
||||
"change_password_form_confirm_password": "确认密码",
|
||||
"change_password_form_description": "{firstName} {lastName} 您好,\n\n这是您首次登录系统,或被管理员要求更改密码。\n请在下方输入新密码。",
|
||||
"change_password_form_description": "{name} 您好,\n\n这是您首次登录系统,或被管理员要求更改密码。\n请在下方输入新密码。",
|
||||
"change_password_form_new_password": "新密码",
|
||||
"change_password_form_password_mismatch": "密码不匹配",
|
||||
"change_password_form_reenter_new_password": "重新输入新的密码",
|
||||
|
||||
@@ -45,7 +45,7 @@ class ImmichTestHelper {
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [dbProvider.overrideWithValue(db)],
|
||||
child: app.getMainWidget(),
|
||||
child: const app.MainWidget(),
|
||||
),
|
||||
);
|
||||
// Post run tasks
|
||||
|
||||
@@ -169,4 +169,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 599d8aeb73728400c15364e734525722250a5382
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
COCOAPODS: 1.11.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Color immichBackgroundColor = const Color(0xFFf6f8fe);
|
||||
Color immichDarkBackgroundColor = const Color.fromARGB(255, 0, 0, 0);
|
||||
Color immichDarkThemePrimaryColor = const Color.fromARGB(255, 173, 203, 250);
|
||||
const Color immichBackgroundColor = Color(0xFFf6f8fe);
|
||||
const Color immichDarkBackgroundColor = Color.fromARGB(255, 0, 0, 0);
|
||||
const Color immichDarkThemePrimaryColor = Color.fromARGB(255, 173, 203, 250);
|
||||
|
||||
@@ -4,22 +4,32 @@ import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/scaffold_error_body.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
extension ScaffoldBody<T> on AsyncValue<T> {
|
||||
static final Logger _scaffoldBodyLog = Logger("ScaffoldBody");
|
||||
extension LogOnError<T> on AsyncValue<T> {
|
||||
static final Logger _asyncErrorLogger = Logger("AsyncValue");
|
||||
|
||||
Widget scaffoldBodyWhen({
|
||||
Widget widgetWhen({
|
||||
bool skipLoadingOnRefresh = true,
|
||||
Widget Function()? onLoading,
|
||||
Widget Function(Object? error, StackTrace? stack)? onError,
|
||||
required Widget Function(T data) onData,
|
||||
Widget? onError,
|
||||
}) {
|
||||
if (isLoading) {
|
||||
return const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
);
|
||||
bool skip = false;
|
||||
if (isRefreshing) {
|
||||
skip = skipLoadingOnRefresh;
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
return onLoading?.call() ??
|
||||
const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasError && !hasValue) {
|
||||
_scaffoldBodyLog.severe("Error occured in AsyncValue", error, stackTrace);
|
||||
return onError ?? const ScaffoldErrorBody();
|
||||
_asyncErrorLogger.severe("Error occured", error, stackTrace);
|
||||
return onError?.call(error, stackTrace) ?? const ScaffoldErrorBody();
|
||||
}
|
||||
|
||||
return onData(requireValue);
|
||||
|
||||
@@ -45,7 +45,7 @@ extension ContextHelper on BuildContext {
|
||||
) =>
|
||||
AutoRouter.of(this).navigate(route);
|
||||
|
||||
// Auto-Push replace route from the current context
|
||||
// Auto-Push replace route from the current context
|
||||
Future<T?> autoReplace<T extends Object?>(PageRouteInfo<dynamic> route) =>
|
||||
AutoRouter.of(this).replace(route);
|
||||
|
||||
|
||||
+33
-31
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
@@ -7,6 +8,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:timezone/data/latest.dart';
|
||||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/modules/backup/background_service/background.service.dart';
|
||||
@@ -28,7 +30,6 @@ import 'package:immich_mobile/shared/providers/app_state.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/shared/services/immich_logger.service.dart';
|
||||
import 'package:immich_mobile/shared/services/local_notification.service.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
import 'package:immich_mobile/utils/http_ssl_cert_override.dart';
|
||||
import 'package:immich_mobile/utils/immich_app_theme.dart';
|
||||
import 'package:immich_mobile/utils/migration.dart';
|
||||
@@ -43,10 +44,11 @@ void main() async {
|
||||
await initApp();
|
||||
await migrateDatabaseIfNeeded(db);
|
||||
HttpOverrides.global = HttpSSLCertOverride();
|
||||
|
||||
runApp(
|
||||
ProviderScope(
|
||||
overrides: [dbProvider.overrideWithValue(db)],
|
||||
child: getMainWidget(),
|
||||
child: const MainWidget(),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -108,16 +110,6 @@ Future<Isar> loadDb() async {
|
||||
return db;
|
||||
}
|
||||
|
||||
Widget getMainWidget() {
|
||||
return EasyLocalization(
|
||||
supportedLocales: locales,
|
||||
path: translationsPath,
|
||||
useFallbackTranslations: true,
|
||||
fallbackLocale: locales.first,
|
||||
child: const ImmichApp(),
|
||||
);
|
||||
}
|
||||
|
||||
class ImmichApp extends ConsumerStatefulWidget {
|
||||
const ImmichApp({super.key});
|
||||
|
||||
@@ -167,10 +159,9 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
||||
// Android 8 does not support transparent app bars
|
||||
final info = await DeviceInfoPlugin().androidInfo;
|
||||
if (info.version.sdkInt <= 26) {
|
||||
overlayStyle =
|
||||
MediaQuery.of(context).platformBrightness == Brightness.light
|
||||
? SystemUiOverlayStyle.light
|
||||
: SystemUiOverlayStyle.dark;
|
||||
overlayStyle = context.isDarkTheme
|
||||
? SystemUiOverlayStyle.dark
|
||||
: SystemUiOverlayStyle.light;
|
||||
}
|
||||
}
|
||||
SystemChrome.setSystemUIOverlayStyle(overlayStyle);
|
||||
@@ -202,22 +193,33 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
||||
supportedLocales: context.supportedLocales,
|
||||
locale: context.locale,
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: Stack(
|
||||
children: [
|
||||
MaterialApp.router(
|
||||
title: 'Immich',
|
||||
debugShowCheckedModeBanner: false,
|
||||
themeMode: ref.watch(immichThemeProvider),
|
||||
darkTheme: immichDarkTheme,
|
||||
theme: immichLightTheme,
|
||||
routeInformationParser: router.defaultRouteParser(),
|
||||
routerDelegate: router.delegate(
|
||||
navigatorObservers: () => [TabNavigationObserver(ref: ref)],
|
||||
),
|
||||
),
|
||||
const ImmichLoadingOverlay(),
|
||||
],
|
||||
home: MaterialApp.router(
|
||||
title: 'Immich',
|
||||
debugShowCheckedModeBanner: false,
|
||||
themeMode: ref.watch(immichThemeProvider),
|
||||
darkTheme: immichDarkTheme,
|
||||
theme: immichLightTheme,
|
||||
routeInformationParser: router.defaultRouteParser(),
|
||||
routerDelegate: router.delegate(
|
||||
navigatorObservers: () => [TabNavigationObserver(ref: ref)],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: prefer-single-widget-per-file
|
||||
class MainWidget extends StatelessWidget {
|
||||
const MainWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return EasyLocalization(
|
||||
supportedLocales: locales,
|
||||
path: translationsPath,
|
||||
useFallbackTranslations: true,
|
||||
fallbackLocale: locales.first,
|
||||
child: const ImmichApp(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/activities/models/activity.model.dart';
|
||||
import 'package:immich_mobile/modules/activities/providers/activity.provider.dart';
|
||||
import 'package:immich_mobile/shared/models/store.dart';
|
||||
import 'package:immich_mobile/shared/ui/confirm_dialog.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||
import 'package:immich_mobile/extensions/datetime_extensions.dart';
|
||||
import 'package:immich_mobile/utils/image_url_builder.dart';
|
||||
@@ -88,7 +88,7 @@ class ActivitiesPage extends HookConsumerWidget {
|
||||
width: 40,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||
image: DecorationImage(
|
||||
image: CachedNetworkImageProvider(
|
||||
getThumbnailUrlForRemoteId(
|
||||
@@ -231,11 +231,8 @@ class ActivitiesPage extends HookConsumerWidget {
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(appBarTitle)),
|
||||
body: activities.maybeWhen(
|
||||
orElse: () {
|
||||
return const Center(child: ImmichLoadingIndicator());
|
||||
},
|
||||
data: (data) {
|
||||
body: activities.widgetWhen(
|
||||
onData: (data) {
|
||||
final liked = data.firstWhereOrNull(
|
||||
(a) =>
|
||||
a.type == ActivityType.like &&
|
||||
|
||||
@@ -65,7 +65,7 @@ class AddToAlbumBottomSheet extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
ref.invalidate(albumDetailProvider(album.id));
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
}
|
||||
|
||||
return Card(
|
||||
|
||||
@@ -43,6 +43,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final newAlbumTitle = ref.watch(albumViewerProvider).editTitleText;
|
||||
final isEditAlbum = ref.watch(albumViewerProvider).isEditAlbum;
|
||||
final isProcessing = useProcessingOverlay();
|
||||
final comments = album.shared
|
||||
? ref.watch(
|
||||
activityStatisticsStateProvider(
|
||||
@@ -52,7 +53,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
: 0;
|
||||
|
||||
deleteAlbum() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
final bool success;
|
||||
if (album.shared) {
|
||||
@@ -74,7 +75,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
);
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
Future<void> showConfirmationDialog() async {
|
||||
@@ -89,7 +90,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, 'Cancel'),
|
||||
onPressed: () => context.pop('Cancel'),
|
||||
child: Text(
|
||||
'Cancel',
|
||||
style: TextStyle(
|
||||
@@ -100,7 +101,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Confirm');
|
||||
context.pop('Confirm');
|
||||
deleteAlbum();
|
||||
},
|
||||
child: Text(
|
||||
@@ -122,7 +123,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
}
|
||||
|
||||
void onLeaveAlbumPressed() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
bool isSuccess =
|
||||
await ref.watch(sharedAlbumProvider.notifier).leaveAlbum(album);
|
||||
@@ -131,7 +132,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
context
|
||||
.autoNavigate(const TabControllerRoute(children: [SharingRoute()]));
|
||||
} else {
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_leave".tr(),
|
||||
@@ -140,11 +141,11 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
);
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void onRemoveFromAlbumPressed() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
bool isSuccess =
|
||||
await ref.watch(sharedAlbumProvider.notifier).removeAssetFromAlbum(
|
||||
@@ -153,12 +154,12 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
);
|
||||
|
||||
if (isSuccess) {
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
selectionDisabled();
|
||||
ref.watch(albumProvider.notifier).getAllAlbums();
|
||||
ref.invalidate(albumDetailProvider(album.id));
|
||||
} else {
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_remove".tr(),
|
||||
@@ -167,7 +168,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
);
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void handleShareAssets(
|
||||
@@ -198,9 +199,9 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
}
|
||||
|
||||
void onShareAssetsTo() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
handleShareAssets(ref, context, selected);
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
buildBottomSheetActions() {
|
||||
@@ -253,7 +254,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
ListTile(
|
||||
leading: const Icon(Icons.person_add_alt_rounded),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
onAddUsers!(album);
|
||||
},
|
||||
title: const Text(
|
||||
@@ -265,7 +266,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
leading: const Icon(Icons.share_rounded),
|
||||
onTap: () {
|
||||
context.autoPush(SharedLinkEditRoute(albumId: album.remoteId));
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
},
|
||||
title: const Text(
|
||||
"control_bottom_app_bar_share",
|
||||
@@ -286,7 +287,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
ListTile(
|
||||
leading: const Icon(Icons.add_photo_alternate_outlined),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
onAddPhotos!(album);
|
||||
},
|
||||
title: const Text(
|
||||
|
||||
@@ -24,10 +24,11 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
final owner = album.owner.value;
|
||||
final userId = ref.watch(authenticationProvider).userId;
|
||||
final activityEnabled = useState(album.activityEnabled);
|
||||
final isProcessing = useProcessingOverlay();
|
||||
final isOwner = owner?.id == userId;
|
||||
|
||||
void showErrorMessage() {
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "shared_album_section_people_action_error".tr(),
|
||||
@@ -37,7 +38,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
void leaveAlbum() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
try {
|
||||
final isSuccess =
|
||||
@@ -54,11 +55,11 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
showErrorMessage();
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void removeUserFromAlbum(User user) async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
try {
|
||||
await ref
|
||||
@@ -70,8 +71,8 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
showErrorMessage();
|
||||
}
|
||||
|
||||
Navigator.pop(context);
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
context.pop();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void handleUserClick(User user) {
|
||||
@@ -180,9 +181,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios_new_rounded),
|
||||
onPressed: () {
|
||||
context.autoPop(null);
|
||||
},
|
||||
onPressed: () => context.autoPop(null),
|
||||
),
|
||||
centerTitle: true,
|
||||
title: Text("translated_text_options".tr()),
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart';
|
||||
@@ -17,7 +18,6 @@ import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/shared/models/album.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
|
||||
@@ -33,6 +33,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
final userId = ref.watch(authenticationProvider).userId;
|
||||
final selection = useState<Set<Asset>>({});
|
||||
final multiSelectEnabled = useState(false);
|
||||
final isProcessing = useProcessingOverlay();
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
@@ -75,24 +76,21 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
|
||||
if (returnPayload != null) {
|
||||
if (returnPayload != null && returnPayload.selectedAssets.isNotEmpty) {
|
||||
// Check if there is new assets add
|
||||
if (returnPayload.selectedAssets.isNotEmpty) {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
var addAssetsResult =
|
||||
await ref.watch(albumServiceProvider).addAdditionalAssetToAlbum(
|
||||
returnPayload.selectedAssets,
|
||||
albumInfo,
|
||||
);
|
||||
var addAssetsResult =
|
||||
await ref.watch(albumServiceProvider).addAdditionalAssetToAlbum(
|
||||
returnPayload.selectedAssets,
|
||||
albumInfo,
|
||||
);
|
||||
|
||||
if (addAssetsResult != null &&
|
||||
addAssetsResult.successfullyAdded > 0) {
|
||||
ref.invalidate(albumDetailProvider(albumId));
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
if (addAssetsResult != null && addAssetsResult.successfullyAdded > 0) {
|
||||
ref.invalidate(albumDetailProvider(albumId));
|
||||
}
|
||||
|
||||
isProcessing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +100,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
if (sharedUserIds != null) {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
var isSuccess = await ref
|
||||
.watch(albumServiceProvider)
|
||||
@@ -112,7 +110,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
ref.invalidate(albumDetailProvider(album.id));
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,13 +258,11 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
error: (error, stackTrace) => AppBar(title: const Text("Error")),
|
||||
loading: () => AppBar(),
|
||||
),
|
||||
body: album.when(
|
||||
data: (data) => WillPopScope(
|
||||
body: album.widgetWhen(
|
||||
onData: (data) => WillPopScope(
|
||||
onWillPop: onWillPop,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
titleFocusNode.unfocus();
|
||||
},
|
||||
onTap: () => titleFocusNode.unfocus(),
|
||||
child: ImmichAssetGrid(
|
||||
renderList: data.renderList,
|
||||
listener: selectionListener,
|
||||
@@ -285,10 +281,6 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
error: (e, _) => Center(child: Text("Error loading album info!\n$e")),
|
||||
loading: () => const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
|
||||
import 'package:immich_mobile/modules/asset_viewer/providers/render_list.provider.dart';
|
||||
@@ -85,12 +86,8 @@ class AssetSelectionPage extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: renderList.when(
|
||||
data: (data) => buildBody(data),
|
||||
error: (error, stackTrace) => Center(
|
||||
child: Text(error.toString()),
|
||||
),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
body: renderList.widgetWhen(
|
||||
onData: (data) => buildBody(data),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/suggested_shared_users.provider.dart';
|
||||
import 'package:immich_mobile/shared/models/album.dart';
|
||||
import 'package:immich_mobile/shared/models/user.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||
|
||||
class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
||||
@@ -137,8 +137,8 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: suggestedShareUsers.when(
|
||||
data: (users) {
|
||||
body: suggestedShareUsers.widgetWhen(
|
||||
onData: (users) {
|
||||
for (var sharedUsers in album.sharedUsers) {
|
||||
users.removeWhere(
|
||||
(u) => u.id == sharedUsers.id || u.id == album.ownerId,
|
||||
@@ -147,10 +147,6 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
||||
|
||||
return buildUserList(users);
|
||||
},
|
||||
error: (e, _) => Text("Error loading suggested users $e"),
|
||||
loading: () => const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/album_title.provider.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
|
||||
@@ -9,7 +10,6 @@ import 'package:immich_mobile/modules/album/providers/suggested_shared_users.pro
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/models/user.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||
|
||||
class SelectUserForSharingPage extends HookConsumerWidget {
|
||||
@@ -42,7 +42,12 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
||||
|
||||
ScaffoldMessenger(
|
||||
child: SnackBar(
|
||||
content: const Text('select_user_for_sharing_page_err_album').tr(),
|
||||
content: Text(
|
||||
'select_user_for_sharing_page_err_album',
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -166,14 +171,10 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: suggestedShareUsers.when(
|
||||
data: (users) {
|
||||
body: suggestedShareUsers.widgetWhen(
|
||||
onData: (users) {
|
||||
return buildUserList(users);
|
||||
},
|
||||
error: (e, _) => Text("Error loading suggested users $e"),
|
||||
loading: () => const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/archive/providers/archive_asset_provider.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||
@@ -48,37 +49,33 @@ class ArchivePage extends HookConsumerWidget {
|
||||
child: SizedBox(
|
||||
height: 64,
|
||||
child: Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
leading: const Icon(
|
||||
Icons.unarchive_rounded,
|
||||
),
|
||||
title: Text(
|
||||
'control_bottom_app_bar_unarchive'.tr(),
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: processing.value
|
||||
? null
|
||||
: () async {
|
||||
processing.value = true;
|
||||
try {
|
||||
await handleArchiveAssets(
|
||||
ref,
|
||||
context,
|
||||
selection.value.toList(),
|
||||
shouldArchive: false,
|
||||
);
|
||||
} finally {
|
||||
processing.value = false;
|
||||
selectionEnabledHook.value = false;
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
child: ListTile(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
),
|
||||
leading: const Icon(
|
||||
Icons.unarchive_rounded,
|
||||
),
|
||||
title: Text(
|
||||
'control_bottom_app_bar_unarchive'.tr(),
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: processing.value
|
||||
? null
|
||||
: () async {
|
||||
processing.value = true;
|
||||
try {
|
||||
await handleArchiveAssets(
|
||||
ref,
|
||||
context,
|
||||
selection.value.toList(),
|
||||
shouldArchive: false,
|
||||
);
|
||||
} finally {
|
||||
processing.value = false;
|
||||
selectionEnabledHook.value = false;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -86,18 +83,13 @@ class ArchivePage extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
return archivedAssets.when(
|
||||
loading: () => Scaffold(
|
||||
appBar: buildAppBar("?"),
|
||||
body: const Center(child: CircularProgressIndicator()),
|
||||
return Scaffold(
|
||||
appBar: archivedAssets.maybeWhen(
|
||||
data: (data) => buildAppBar(data.totalAssets.toString()),
|
||||
orElse: () => buildAppBar("?"),
|
||||
),
|
||||
error: (error, stackTrace) => Scaffold(
|
||||
appBar: buildAppBar("Error"),
|
||||
body: Center(child: Text(error.toString())),
|
||||
),
|
||||
data: (data) => Scaffold(
|
||||
appBar: buildAppBar(data.totalAssets.toString()),
|
||||
body: data.isEmpty
|
||||
body: archivedAssets.widgetWhen(
|
||||
onData: (data) => data.isEmpty
|
||||
? Center(
|
||||
child: Text('archive_page_no_archived_assets'.tr()),
|
||||
)
|
||||
|
||||
@@ -62,8 +62,14 @@ class AdvancedBottomSheet extends HookConsumerWidget {
|
||||
ClipboardData(text: assetDetail.toString()),
|
||||
).then((_) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text("Copied to clipboard"),
|
||||
SnackBar(
|
||||
content: Text(
|
||||
"Copied to clipboard",
|
||||
style: context.textTheme.bodyLarge
|
||||
?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -514,7 +514,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
||||
currentAsset,
|
||||
stackElements.elementAt(stackIndex.value),
|
||||
);
|
||||
Navigator.pop(ctx);
|
||||
ctx.pop();
|
||||
context.autoPop();
|
||||
},
|
||||
title: const Text(
|
||||
@@ -541,7 +541,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
||||
stackElements.elementAt(1),
|
||||
childrenToRemove: [currentAsset],
|
||||
);
|
||||
Navigator.pop(ctx);
|
||||
ctx.pop();
|
||||
context.autoPop();
|
||||
} else {
|
||||
await ref.read(assetStackServiceProvider).updateStack(
|
||||
@@ -551,7 +551,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
||||
],
|
||||
);
|
||||
removeAssetFromStack();
|
||||
Navigator.pop(ctx);
|
||||
ctx.pop();
|
||||
}
|
||||
},
|
||||
title: const Text(
|
||||
@@ -569,7 +569,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
||||
currentAsset,
|
||||
childrenToRemove: stack,
|
||||
);
|
||||
Navigator.pop(ctx);
|
||||
ctx.pop();
|
||||
context.autoPop();
|
||||
},
|
||||
title: const Text(
|
||||
|
||||
@@ -42,6 +42,9 @@ class BackupService {
|
||||
|
||||
try {
|
||||
return await _apiService.assetApi.getUserAssetsByDeviceId(deviceId);
|
||||
|
||||
// TODO! Start using this in 1.92.0
|
||||
// return await _apiService.assetApi.getAllUserAssetsByDeviceId(deviceId);
|
||||
} catch (e) {
|
||||
debugPrint('Error [getDeviceBackupAsset] ${e.toString()}');
|
||||
return null;
|
||||
@@ -275,13 +278,6 @@ class BackupService {
|
||||
|
||||
req.files.add(assetRawUploadData);
|
||||
|
||||
if (entity.isLivePhoto) {
|
||||
var livePhotoRawUploadData = await _getLivePhotoFile(entity);
|
||||
if (livePhotoRawUploadData != null) {
|
||||
req.files.add(livePhotoRawUploadData);
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentUploadAssetCb(
|
||||
CurrentUploadAsset(
|
||||
id: entity.id,
|
||||
@@ -296,6 +292,29 @@ class BackupService {
|
||||
var response =
|
||||
await httpClient.send(req, cancellationToken: cancelToken);
|
||||
|
||||
// Send live photo separately
|
||||
if (entity.isLivePhoto) {
|
||||
var livePhotoRawUploadData = await _getLivePhotoFile(entity);
|
||||
if (livePhotoRawUploadData != null) {
|
||||
var livePhotoReq = MultipartRequest(
|
||||
req.method,
|
||||
req.url,
|
||||
onProgress: req.onProgress,
|
||||
)
|
||||
..headers.addAll(req.headers)
|
||||
..fields.addAll(req.fields);
|
||||
|
||||
livePhotoReq.files.add(livePhotoRawUploadData);
|
||||
// Send live photo only if the non-motion part is successful
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
response = await httpClient.send(
|
||||
livePhotoReq,
|
||||
cancellationToken: cancelToken,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// asset is a duplicate (already exists on the server)
|
||||
duplicatedAssetIds.add(entity.id);
|
||||
@@ -353,7 +372,7 @@ class BackupService {
|
||||
var fileStream = motionFile.openRead();
|
||||
String fileName = p.basename(motionFile.path);
|
||||
return http.MultipartFile(
|
||||
"livePhotoData",
|
||||
"assetData",
|
||||
fileStream,
|
||||
motionFile.lengthSync(),
|
||||
filename: fileName,
|
||||
|
||||
@@ -229,6 +229,9 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
final snackBar = SnackBar(
|
||||
content: Text(
|
||||
msg.tr(),
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||
@@ -62,22 +63,18 @@ class FavoritesPage extends HookConsumerWidget {
|
||||
child: SizedBox(
|
||||
height: 64,
|
||||
child: Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
leading: const Icon(
|
||||
Icons.star_border,
|
||||
),
|
||||
title: const Text(
|
||||
"Unfavorite",
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: processing.value ? null : unfavorite,
|
||||
),
|
||||
],
|
||||
child: ListTile(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
),
|
||||
leading: const Icon(
|
||||
Icons.star_border,
|
||||
),
|
||||
title: const Text(
|
||||
"Unfavorite",
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: processing.value ? null : unfavorite,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -87,10 +84,8 @@ class FavoritesPage extends HookConsumerWidget {
|
||||
|
||||
return Scaffold(
|
||||
appBar: buildAppBar(),
|
||||
body: ref.watch(favoriteAssetsProvider).when(
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, stackTrace) => Center(child: Text(error.toString())),
|
||||
data: (data) => data.isEmpty
|
||||
body: ref.watch(favoriteAssetsProvider).widgetWhen(
|
||||
onData: (data) => data.isEmpty
|
||||
? Center(
|
||||
child: Text('favorites_page_no_favorites'.tr()),
|
||||
)
|
||||
|
||||
@@ -5,13 +5,13 @@ import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/modules/asset_viewer/providers/render_list.provider.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid_view.dart';
|
||||
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
|
||||
class ImmichAssetGrid extends HookConsumerWidget {
|
||||
@@ -130,12 +130,8 @@ class ImmichAssetGrid extends HookConsumerWidget {
|
||||
if (renderList != null) return buildAssetGridView(renderList!);
|
||||
|
||||
final renderListFuture = ref.watch(renderListProvider(assets!));
|
||||
return renderListFuture.when(
|
||||
data: (renderList) => buildAssetGridView(renderList),
|
||||
error: (err, stack) => Center(child: Text("$err")),
|
||||
loading: () => const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
return renderListFuture.widgetWhen(
|
||||
onData: (renderList) => buildAssetGridView(renderList),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,9 @@ class ThumbnailImage extends StatelessWidget {
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.decelerate,
|
||||
decoration: BoxDecoration(
|
||||
border: multiselectEnabled && isSelected
|
||||
? Border.all(
|
||||
|
||||
@@ -28,6 +28,7 @@ import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_app_bar.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
import 'package:immich_mobile/utils/selection_handlers.dart';
|
||||
|
||||
class HomePage extends HookConsumerWidget {
|
||||
@@ -50,7 +51,7 @@ class HomePage extends HookConsumerWidget {
|
||||
|
||||
final tipOneOpacity = useState(0.0);
|
||||
final refreshCount = useState(0);
|
||||
final processing = useState(false);
|
||||
final processing = useProcessingOverlay();
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
@@ -212,10 +213,10 @@ class HomePage extends HookConsumerWidget {
|
||||
processing.value = true;
|
||||
selectionEnabledHook.value = false;
|
||||
try {
|
||||
ref.read(manualUploadProvider.notifier).uploadAssets(
|
||||
context,
|
||||
selection.value.where((a) => a.storage == AssetState.local),
|
||||
);
|
||||
ref.read(manualUploadProvider.notifier).uploadAssets(
|
||||
context,
|
||||
selection.value.where((a) => a.storage == AssetState.local),
|
||||
);
|
||||
} finally {
|
||||
processing.value = false;
|
||||
}
|
||||
@@ -323,16 +324,12 @@ class HomePage extends HookConsumerWidget {
|
||||
} else {
|
||||
refreshCount.value++;
|
||||
// set counter back to 0 if user does not request refresh again
|
||||
Timer(const Duration(seconds: 4), () {
|
||||
refreshCount.value = 0;
|
||||
});
|
||||
Timer(const Duration(seconds: 4), () => refreshCount.value = 0);
|
||||
}
|
||||
}
|
||||
|
||||
buildLoadingIndicator() {
|
||||
Timer(const Duration(seconds: 2), () {
|
||||
tipOneOpacity.value = 1;
|
||||
});
|
||||
Timer(const Duration(seconds: 2), () => tipOneOpacity.value = 1);
|
||||
|
||||
return Center(
|
||||
child: Column(
|
||||
@@ -415,7 +412,6 @@ class HomePage extends HookConsumerWidget {
|
||||
selectionAssetState: selectionAssetState.value,
|
||||
onStack: onStack,
|
||||
),
|
||||
if (processing.value) const Center(child: ImmichLoadingIndicator()),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -48,7 +48,7 @@ class LoginForm extends HookConsumerWidget {
|
||||
/// Fetch the server login credential and enables oAuth login if necessary
|
||||
/// Returns true if successful, false otherwise
|
||||
Future<bool> getServerLoginCredential() async {
|
||||
final serverUrl = serverEndpointController.text.trim();
|
||||
final serverUrl = sanitizeUrl(serverEndpointController.text);
|
||||
|
||||
// Guard empty URL
|
||||
if (serverUrl.isEmpty) {
|
||||
@@ -127,6 +127,12 @@ class LoginForm extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
populateTestLoginInfo() {
|
||||
usernameController.text = 'demo@immich.app';
|
||||
passwordController.text = 'demo';
|
||||
serverEndpointController.text = 'https://demo.immich.app';
|
||||
}
|
||||
|
||||
populateTestLoginInfo1() {
|
||||
usernameController.text = 'testuser@email.com';
|
||||
passwordController.text = 'password';
|
||||
serverEndpointController.text = 'http://10.1.15.216:2283/api';
|
||||
@@ -144,7 +150,7 @@ class LoginForm extends HookConsumerWidget {
|
||||
await ref.read(authenticationProvider.notifier).login(
|
||||
usernameController.text,
|
||||
passwordController.text,
|
||||
serverEndpointController.text.trim(),
|
||||
sanitizeUrl(serverEndpointController.text),
|
||||
);
|
||||
if (isAuthenticated) {
|
||||
// Resume backup (if enable) then navigate
|
||||
@@ -181,7 +187,7 @@ class LoginForm extends HookConsumerWidget {
|
||||
|
||||
try {
|
||||
oAuthServerConfig = await oAuthService
|
||||
.getOAuthServerConfig(serverEndpointController.text);
|
||||
.getOAuthServerConfig(sanitizeUrl(serverEndpointController.text));
|
||||
|
||||
isLoading.value = true;
|
||||
} catch (e) {
|
||||
@@ -203,7 +209,7 @@ class LoginForm extends HookConsumerWidget {
|
||||
.watch(authenticationProvider.notifier)
|
||||
.setSuccessLoginInfo(
|
||||
accessToken: loginResponseDto.accessToken,
|
||||
serverUrl: serverEndpointController.text,
|
||||
serverUrl: sanitizeUrl(serverEndpointController.text),
|
||||
);
|
||||
|
||||
if (isSuccess) {
|
||||
@@ -299,7 +305,7 @@ class LoginForm extends HookConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
serverEndpointController.text,
|
||||
sanitizeUrl(serverEndpointController.text),
|
||||
style: context.textTheme.displaySmall,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
@@ -387,6 +393,7 @@ class LoginForm extends HookConsumerWidget {
|
||||
children: [
|
||||
GestureDetector(
|
||||
onDoubleTap: () => populateTestLoginInfo(),
|
||||
onLongPress: () => populateTestLoginInfo1(),
|
||||
child: RotationTransition(
|
||||
turns: logoAnimationController,
|
||||
child: const ImmichLogo(
|
||||
|
||||
@@ -17,7 +17,7 @@ class MemoryLane extends HookConsumerWidget {
|
||||
.whenData(
|
||||
(memories) => memories != null
|
||||
? Container(
|
||||
margin: const EdgeInsets.only(top: 10),
|
||||
margin: const EdgeInsets.only(top: 10, left: 10),
|
||||
height: 200,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||
import 'package:immich_mobile/modules/partner/providers/partner.provider.dart';
|
||||
import 'package:immich_mobile/shared/models/user.dart';
|
||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||
|
||||
class PartnerDetailPage extends HookConsumerWidget {
|
||||
@@ -71,8 +71,8 @@ class PartnerDetailPage extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: assets.when(
|
||||
data: (renderList) => renderList.isEmpty
|
||||
body: assets.widgetWhen(
|
||||
onData: (renderList) => renderList.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text(
|
||||
@@ -84,8 +84,6 @@ class PartnerDetailPage extends HookConsumerWidget {
|
||||
onRefresh: () =>
|
||||
ref.read(assetProvider.notifier).getPartnerAssets(partner),
|
||||
),
|
||||
error: (e, _) => Text("Error loading partners:\n$e"),
|
||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/partner/providers/partner.provider.dart';
|
||||
import 'package:immich_mobile/modules/partner/services/partner.service.dart';
|
||||
import 'package:immich_mobile/shared/models/user.dart';
|
||||
@@ -34,7 +35,7 @@ class PartnerPage extends HookConsumerWidget {
|
||||
children: [
|
||||
for (User u in users)
|
||||
SimpleDialogOption(
|
||||
onPressed: () => Navigator.pop(context, u),
|
||||
onPressed: () => context.pop(u),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
@@ -70,8 +71,7 @@ class PartnerPage extends HookConsumerWidget {
|
||||
builder: (BuildContext context) {
|
||||
return ConfirmDialog(
|
||||
title: "partner_page_stop_sharing_title",
|
||||
content:
|
||||
"partner_page_stop_sharing_content".tr(args: [u.name]),
|
||||
content: "partner_page_stop_sharing_content".tr(args: [u.name]),
|
||||
onOk: () => ref.read(partnerServiceProvider).removePartner(u),
|
||||
);
|
||||
},
|
||||
@@ -118,6 +118,7 @@ class PartnerPage extends HookConsumerWidget {
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
@@ -126,12 +127,15 @@ class PartnerPage extends HookConsumerWidget {
|
||||
style: TextStyle(fontSize: 14),
|
||||
).tr(),
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
onPressed: availableUsers.whenOrNull(
|
||||
data: (data) => addNewUsersHandler,
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: availableUsers.whenOrNull(
|
||||
data: (data) => addNewUsersHandler,
|
||||
),
|
||||
icon: const Icon(Icons.person_add),
|
||||
label: const Text("partner_page_add_partner").tr(),
|
||||
),
|
||||
icon: const Icon(Icons.person_add),
|
||||
label: const Text("partner_page_add_partner").tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||
import 'package:immich_mobile/modules/search/providers/all_motion_photos.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
|
||||
class AllMotionPhotosPage extends HookConsumerWidget {
|
||||
const AllMotionPhotosPage({super.key});
|
||||
@@ -21,14 +21,10 @@ class AllMotionPhotosPage extends HookConsumerWidget {
|
||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||
),
|
||||
),
|
||||
body: motionPhotos.when(
|
||||
data: (assets) => ImmichAssetGrid(
|
||||
body: motionPhotos.widgetWhen(
|
||||
onData: (assets) => ImmichAssetGrid(
|
||||
assets: assets,
|
||||
),
|
||||
error: (e, s) => Text(e.toString()),
|
||||
loading: () => const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
||||
import 'package:immich_mobile/modules/search/ui/explore_grid.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
|
||||
class AllPeoplePage extends HookConsumerWidget {
|
||||
const AllPeoplePage({super.key});
|
||||
@@ -23,12 +23,8 @@ class AllPeoplePage extends HookConsumerWidget {
|
||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||
),
|
||||
),
|
||||
body: curatedPeople.when(
|
||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
||||
error: (err, stack) => Center(
|
||||
child: Text('Error: $err'),
|
||||
),
|
||||
data: (people) => ExploreGrid(
|
||||
body: curatedPeople.widgetWhen(
|
||||
onData: (people) => ExploreGrid(
|
||||
isPeople: true,
|
||||
curatedContent: people,
|
||||
),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||
import 'package:immich_mobile/modules/search/providers/all_video_assets.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
|
||||
class AllVideosPage extends HookConsumerWidget {
|
||||
const AllVideosPage({super.key});
|
||||
@@ -21,14 +21,10 @@ class AllVideosPage extends HookConsumerWidget {
|
||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||
),
|
||||
),
|
||||
body: videos.when(
|
||||
data: (assets) => ImmichAssetGrid(
|
||||
body: videos.widgetWhen(
|
||||
onData: (assets) => ImmichAssetGrid(
|
||||
assets: assets,
|
||||
),
|
||||
error: (e, s) => Text(e.toString()),
|
||||
loading: () => const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/search/models/curated_content.dart';
|
||||
import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart';
|
||||
import 'package:immich_mobile/modules/search/ui/explore_grid.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class CuratedLocationPage extends HookConsumerWidget {
|
||||
@@ -26,12 +26,8 @@ class CuratedLocationPage extends HookConsumerWidget {
|
||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||
),
|
||||
),
|
||||
body: curatedLocation.when(
|
||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
||||
error: (err, stack) => Center(
|
||||
child: Text('Error: $err'),
|
||||
),
|
||||
data: (curatedLocations) => ExploreGrid(
|
||||
body: curatedLocation.widgetWhen(
|
||||
onData: (curatedLocations) => ExploreGrid(
|
||||
curatedContent: curatedLocations
|
||||
.map(
|
||||
(l) => CuratedContent(
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'
|
||||
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
||||
import 'package:immich_mobile/modules/search/ui/person_name_edit_form.dart';
|
||||
import 'package:immich_mobile/shared/models/store.dart' as isar_store;
|
||||
import 'package:immich_mobile/shared/ui/scaffold_error_body.dart';
|
||||
import 'package:immich_mobile/utils/image_url_builder.dart';
|
||||
|
||||
class PersonResultPage extends HookConsumerWidget {
|
||||
@@ -112,7 +111,7 @@ class PersonResultPage extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ref.watch(personAssetsProvider(personId)).scaffoldBodyWhen(
|
||||
body: ref.watch(personAssetsProvider(personId)).widgetWhen(
|
||||
onData: (renderList) => ImmichAssetGrid(
|
||||
renderList: renderList,
|
||||
topWidget: Padding(
|
||||
@@ -137,7 +136,6 @@ class PersonResultPage extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
onError: const ScaffoldErrorBody(icon: Icons.person_off_outlined),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||
import 'package:immich_mobile/modules/search/providers/recently_added.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
|
||||
class RecentlyAddedPage extends HookConsumerWidget {
|
||||
const RecentlyAddedPage({super.key});
|
||||
@@ -21,14 +21,10 @@ class RecentlyAddedPage extends HookConsumerWidget {
|
||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||
),
|
||||
),
|
||||
body: recents.when(
|
||||
data: (searchResponse) => ImmichAssetGrid(
|
||||
body: recents.widgetWhen(
|
||||
onData: (searchResponse) => ImmichAssetGrid(
|
||||
assets: searchResponse,
|
||||
),
|
||||
error: (e, s) => Text(e.toString()),
|
||||
loading: () => const Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/search/models/curated_content.dart';
|
||||
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
||||
@@ -15,7 +16,7 @@ import 'package:immich_mobile/modules/search/ui/search_row_title.dart';
|
||||
import 'package:immich_mobile/modules/search/ui/search_suggestion_list.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/scaffold_error_body.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class SearchPage extends HookConsumerWidget {
|
||||
@@ -73,10 +74,9 @@ class SearchPage extends HookConsumerWidget {
|
||||
buildPeople() {
|
||||
return SizedBox(
|
||||
height: imageSize,
|
||||
child: curatedPeople.when(
|
||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
||||
error: (err, stack) => Center(child: Text('Error: $err')),
|
||||
data: (people) => CuratedPeopleRow(
|
||||
child: curatedPeople.widgetWhen(
|
||||
onError: (error, stack) => const ScaffoldErrorBody(withIcon: false),
|
||||
onData: (people) => CuratedPeopleRow(
|
||||
content: people.take(12).toList(),
|
||||
onTap: (content, index) {
|
||||
context.autoPush(
|
||||
@@ -97,10 +97,9 @@ class SearchPage extends HookConsumerWidget {
|
||||
buildPlaces() {
|
||||
return SizedBox(
|
||||
height: imageSize,
|
||||
child: curatedLocation.when(
|
||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
||||
error: (err, stack) => Center(child: Text('Error: $err')),
|
||||
data: (locations) => CuratedPlacesRow(
|
||||
child: curatedLocation.widgetWhen(
|
||||
onError: (error, stack) => const ScaffoldErrorBody(withIcon: false),
|
||||
onData: (locations) => CuratedPlacesRow(
|
||||
isMapEnabled: isMapEnabled,
|
||||
content: locations
|
||||
.map(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/settings/ui/advanced_settings/advanced_settings.dart';
|
||||
import 'package:immich_mobile/modules/settings/ui/asset_list_settings/asset_list_settings.dart';
|
||||
import 'package:immich_mobile/modules/settings/ui/local_storage_settings/local_storage_settings.dart';
|
||||
@@ -18,9 +19,7 @@ class SettingsPage extends HookConsumerWidget {
|
||||
leading: IconButton(
|
||||
iconSize: 20,
|
||||
splashRadius: 24,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
onPressed: () => context.pop(),
|
||||
icon: const Icon(Icons.arrow_back_ios_new_rounded),
|
||||
),
|
||||
automaticallyImplyLeading: false,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:math' as math;
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
@@ -26,13 +27,13 @@ class SharedLinkItem extends ConsumerWidget {
|
||||
}
|
||||
|
||||
Widget getExpiryDuration(bool isDarkMode) {
|
||||
var expiresText = "Expires ∞";
|
||||
var expiresText = "shared_link_expires_never".tr();
|
||||
if (sharedLink.expiresAt != null) {
|
||||
if (isExpired()) {
|
||||
return Text(
|
||||
"Expired",
|
||||
"shared_link_expired",
|
||||
style: TextStyle(color: Colors.red[300]),
|
||||
);
|
||||
).tr();
|
||||
}
|
||||
final difference = sharedLink.expiresAt!.difference(DateTime.now());
|
||||
debugPrint("Difference: $difference");
|
||||
@@ -41,13 +42,15 @@ class SharedLinkItem extends ConsumerWidget {
|
||||
if (difference.inHours % 24 > 12) {
|
||||
dayDifference += 1;
|
||||
}
|
||||
expiresText = "in $dayDifference days";
|
||||
expiresText = "shared_link_expires_days".plural(dayDifference);
|
||||
} else if (difference.inHours > 0) {
|
||||
expiresText = "in ${difference.inHours} hours";
|
||||
expiresText = "shared_link_expires_hours".plural(difference.inHours);
|
||||
} else if (difference.inMinutes > 0) {
|
||||
expiresText = "in ${difference.inMinutes} minutes";
|
||||
expiresText =
|
||||
"shared_link_expires_minutes".plural(difference.inMinutes);
|
||||
} else if (difference.inSeconds > 0) {
|
||||
expiresText = "in ${difference.inSeconds} seconds";
|
||||
expiresText =
|
||||
"shared_link_expires_seconds".plural(difference.inSeconds);
|
||||
}
|
||||
}
|
||||
return Text(
|
||||
@@ -72,7 +75,7 @@ class SharedLinkItem extends ConsumerWidget {
|
||||
context: context,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
toastType: ToastType.error,
|
||||
msg: 'Cannot fetch the server url',
|
||||
msg: "shared_link_error_server_url_fetch".tr(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -83,11 +86,14 @@ class SharedLinkItem extends ConsumerWidget {
|
||||
),
|
||||
).then((_) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
"Copied to clipboard",
|
||||
),
|
||||
duration: Duration(seconds: 2),
|
||||
"shared_link_clipboard_copied_massage",
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -163,9 +169,12 @@ class SharedLinkItem extends ConsumerWidget {
|
||||
Widget buildBottomInfo() {
|
||||
return Row(
|
||||
children: [
|
||||
if (sharedLink.allowUpload) buildInfoChip("Upload"),
|
||||
if (sharedLink.allowDownload) buildInfoChip("Download"),
|
||||
if (sharedLink.showMetadata) buildInfoChip("EXIF"),
|
||||
if (sharedLink.allowUpload)
|
||||
buildInfoChip("shared_link_info_chip_upload".tr()),
|
||||
if (sharedLink.allowDownload)
|
||||
buildInfoChip("shared_link_info_chip_download".tr()),
|
||||
if (sharedLink.showMetadata)
|
||||
buildInfoChip("shared_link_info_chip_metadata".tr()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -275,7 +275,12 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
||||
).then((_) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text("shared_link_clipboard_copied_massage").tr(),
|
||||
content: Text(
|
||||
"shared_link_clipboard_copied_massage",
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2,11 +2,11 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/shared_link/models/shared_link.dart';
|
||||
import 'package:immich_mobile/modules/shared_link/providers/shared_link.provider.dart';
|
||||
import 'package:immich_mobile/modules/shared_link/ui/shared_link_item.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
|
||||
class SharedLinkPage extends HookConsumerWidget {
|
||||
const SharedLinkPage({Key? key}) : super(key: key);
|
||||
@@ -18,7 +18,10 @@ class SharedLinkPage extends HookConsumerWidget {
|
||||
useEffect(
|
||||
() {
|
||||
ref.read(sharedLinksStateProvider.notifier).fetchLinks();
|
||||
return () => ref.invalidate(sharedLinksStateProvider);
|
||||
return () {
|
||||
if (!context.mounted) return;
|
||||
ref.invalidate(sharedLinksStateProvider);
|
||||
};
|
||||
},
|
||||
[],
|
||||
);
|
||||
@@ -113,11 +116,10 @@ class SharedLinkPage extends HookConsumerWidget {
|
||||
centerTitle: false,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: sharedLinks.when(
|
||||
data: (links) =>
|
||||
child: sharedLinks.widgetWhen(
|
||||
onError: (error, stackTrace) => buildNoShares(),
|
||||
onData: (links) =>
|
||||
links.isNotEmpty ? buildSharesList(links) : buildNoShares(),
|
||||
error: (error, stackTrace) => buildNoShares(),
|
||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/delete_dialog.dart';
|
||||
@@ -11,8 +12,8 @@ import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/confirm_dialog.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
|
||||
class TrashPage extends HookConsumerWidget {
|
||||
const TrashPage({super.key});
|
||||
@@ -24,7 +25,7 @@ class TrashPage extends HookConsumerWidget {
|
||||
ref.watch(serverInfoProvider.select((v) => v.serverConfig.trashDays));
|
||||
final selectionEnabledHook = useState(false);
|
||||
final selection = useState(<Asset>{});
|
||||
final processing = useState(false);
|
||||
final processing = useProcessingOverlay();
|
||||
|
||||
void selectionListener(
|
||||
bool multiselect,
|
||||
@@ -229,18 +230,13 @@ class TrashPage extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
return trashedAssets.when(
|
||||
loading: () => Scaffold(
|
||||
appBar: buildAppBar("?"),
|
||||
body: const Center(child: CircularProgressIndicator()),
|
||||
return Scaffold(
|
||||
appBar: trashedAssets.maybeWhen(
|
||||
orElse: () => buildAppBar("?"),
|
||||
data: (data) => buildAppBar(data.totalAssets.toString()),
|
||||
),
|
||||
error: (error, stackTrace) => Scaffold(
|
||||
appBar: buildAppBar("!"),
|
||||
body: Center(child: Text(error.toString())),
|
||||
),
|
||||
data: (data) => Scaffold(
|
||||
appBar: buildAppBar(data.totalAssets.toString()),
|
||||
body: data.isEmpty
|
||||
body: trashedAssets.widgetWhen(
|
||||
onData: (data) => data.isEmpty
|
||||
? Center(
|
||||
child: Text('trash_page_no_assets'.tr()),
|
||||
)
|
||||
@@ -254,11 +250,9 @@ class TrashPage extends HookConsumerWidget {
|
||||
showMultiSelectIndicator: false,
|
||||
showStack: true,
|
||||
topWidget: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 24,
|
||||
bottom: 24,
|
||||
left: 12,
|
||||
right: 12,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 24,
|
||||
),
|
||||
child: const Text(
|
||||
"trash_page_info",
|
||||
@@ -267,8 +261,6 @@ class TrashPage extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
if (selectionEnabledHook.value) buildBottomBar(),
|
||||
if (processing.value)
|
||||
const Center(child: ImmichLoadingIndicator()),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -21,7 +21,7 @@ class ImmichLoadingIndicator extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(15),
|
||||
child: const CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
strokeWidth: 2,
|
||||
strokeWidth: 3,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
|
||||
// Error widget to be used in Scaffold when an AsyncError is received
|
||||
class ScaffoldErrorBody extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final bool withIcon;
|
||||
|
||||
const ScaffoldErrorBody({this.icon = Icons.error_outline, super.key});
|
||||
const ScaffoldErrorBody({super.key, this.withIcon = true});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -14,19 +14,22 @@ class ScaffoldErrorBody extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
Text(
|
||||
"scaffold_body_error_occured",
|
||||
style:
|
||||
TextStyle(fontSize: 14, fontWeight: FontWeight.bold, height: 3),
|
||||
style: context.textTheme.displayMedium,
|
||||
textAlign: TextAlign.center,
|
||||
).tr(),
|
||||
Center(
|
||||
child: Icon(
|
||||
icon,
|
||||
size: 100,
|
||||
color: context.themeData.iconTheme.color?.withOpacity(0.5),
|
||||
if (withIcon)
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
child: Icon(
|
||||
Icons.error_outline,
|
||||
size: 100,
|
||||
color: context.themeData.iconTheme.color?.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,14 @@ class AppLogDetailPage extends HookConsumerWidget {
|
||||
Clipboard.setData(ClipboardData(text: stackTrace))
|
||||
.then((_) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text("Copied to clipboard")),
|
||||
SnackBar(
|
||||
content: Text(
|
||||
"Copied to clipboard",
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
@@ -98,7 +105,14 @@ class AppLogDetailPage extends HookConsumerWidget {
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: message)).then((_) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text("Copied to clipboard")),
|
||||
SnackBar(
|
||||
content: Text(
|
||||
"Copied to clipboard",
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,41 +1,64 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
|
||||
class ImmichLoadingOverlay extends StatelessWidget {
|
||||
const ImmichLoadingOverlay({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
final _loadingEntry = OverlayEntry(
|
||||
builder: (context) => SizedBox.square(
|
||||
dimension: double.infinity,
|
||||
child: DecoratedBox(
|
||||
decoration:
|
||||
BoxDecoration(color: context.colorScheme.surface.withAlpha(200)),
|
||||
child: const Center(child: ImmichLoadingIndicator()),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
ValueNotifier<bool> useProcessingOverlay() {
|
||||
return use(const _LoadingOverlay());
|
||||
}
|
||||
|
||||
class _LoadingOverlay extends Hook<ValueNotifier<bool>> {
|
||||
const _LoadingOverlay();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder<bool>(
|
||||
valueListenable:
|
||||
ImmichLoadingOverlayController.appLoader.loaderShowingNotifier,
|
||||
builder: (context, shouldShow, child) {
|
||||
return shouldShow
|
||||
? const Scaffold(
|
||||
backgroundColor: Colors.black54,
|
||||
body: Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
)
|
||||
: const SizedBox();
|
||||
},
|
||||
);
|
||||
}
|
||||
_LoadingOverlayState createState() => _LoadingOverlayState();
|
||||
}
|
||||
|
||||
class ImmichLoadingOverlayController {
|
||||
static final ImmichLoadingOverlayController appLoader =
|
||||
ImmichLoadingOverlayController();
|
||||
ValueNotifier<bool> loaderShowingNotifier = ValueNotifier(false);
|
||||
ValueNotifier<String> loaderTextNotifier = ValueNotifier('error message');
|
||||
class _LoadingOverlayState
|
||||
extends HookState<ValueNotifier<bool>, _LoadingOverlay> {
|
||||
late final _isProcessing = ValueNotifier(false)..addListener(_listener);
|
||||
OverlayEntry? overlayEntry;
|
||||
|
||||
void show() {
|
||||
loaderShowingNotifier.value = true;
|
||||
void _listener() {
|
||||
setState(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (_isProcessing.value) {
|
||||
overlayEntry?.remove();
|
||||
overlayEntry = _loadingEntry;
|
||||
Overlay.of(context).insert(_loadingEntry);
|
||||
} else {
|
||||
overlayEntry?.remove();
|
||||
overlayEntry = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void hide() {
|
||||
loaderShowingNotifier.value = false;
|
||||
@override
|
||||
ValueNotifier<bool> build(BuildContext context) {
|
||||
return _isProcessing;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_isProcessing.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Object? get debugValue => _isProcessing.value;
|
||||
|
||||
@override
|
||||
String get debugLabel => 'useProcessingOverlay<>';
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ ThemeData immichLightTheme = ThemeData(
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
titleTextStyle: const TextStyle(
|
||||
appBarTheme: const AppBarTheme(
|
||||
titleTextStyle: TextStyle(
|
||||
fontFamily: 'Overpass',
|
||||
color: Colors.indigo,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -61,7 +61,7 @@ ThemeData immichLightTheme = ThemeData(
|
||||
scrolledUnderElevation: 0,
|
||||
centerTitle: true,
|
||||
),
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: immichBackgroundColor,
|
||||
selectedItemColor: Colors.indigo,
|
||||
@@ -69,7 +69,7 @@ ThemeData immichLightTheme = ThemeData(
|
||||
cardTheme: const CardTheme(
|
||||
surfaceTintColor: Colors.transparent,
|
||||
),
|
||||
drawerTheme: DrawerThemeData(
|
||||
drawerTheme: const DrawerThemeData(
|
||||
backgroundColor: immichBackgroundColor,
|
||||
),
|
||||
textTheme: const TextTheme(
|
||||
@@ -162,7 +162,7 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
hintColor: Colors.grey[600],
|
||||
fontFamily: 'Overpass',
|
||||
snackBarTheme: SnackBarThemeData(
|
||||
contentTextStyle: TextStyle(
|
||||
contentTextStyle: const TextStyle(
|
||||
fontFamily: 'Overpass',
|
||||
color: immichDarkThemePrimaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -174,35 +174,35 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
foregroundColor: immichDarkThemePrimaryColor,
|
||||
),
|
||||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
appBarTheme: const AppBarTheme(
|
||||
titleTextStyle: TextStyle(
|
||||
fontFamily: 'Overpass',
|
||||
color: immichDarkThemePrimaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
),
|
||||
backgroundColor: const Color.fromARGB(255, 32, 33, 35),
|
||||
backgroundColor: Color.fromARGB(255, 32, 33, 35),
|
||||
foregroundColor: immichDarkThemePrimaryColor,
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
centerTitle: true,
|
||||
),
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: const Color.fromARGB(255, 35, 36, 37),
|
||||
backgroundColor: Color.fromARGB(255, 35, 36, 37),
|
||||
selectedItemColor: immichDarkThemePrimaryColor,
|
||||
),
|
||||
drawerTheme: DrawerThemeData(
|
||||
backgroundColor: immichDarkBackgroundColor,
|
||||
scrimColor: Colors.white.withOpacity(0.1),
|
||||
),
|
||||
textTheme: TextTheme(
|
||||
displayLarge: const TextStyle(
|
||||
textTheme: const TextTheme(
|
||||
displayLarge: TextStyle(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color.fromARGB(255, 255, 255, 255),
|
||||
),
|
||||
displayMedium: const TextStyle(
|
||||
displayMedium: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color.fromARGB(255, 255, 255, 255),
|
||||
@@ -212,15 +212,15 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: immichDarkThemePrimaryColor,
|
||||
),
|
||||
titleSmall: const TextStyle(
|
||||
titleSmall: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
titleMedium: const TextStyle(
|
||||
titleMedium: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
titleLarge: const TextStyle(
|
||||
titleLarge: TextStyle(
|
||||
fontSize: 26.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
@@ -258,7 +258,7 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
dialogTheme: const DialogTheme(
|
||||
surfaceTintColor: Colors.transparent,
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: immichDarkThemePrimaryColor,
|
||||
@@ -267,12 +267,12 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
labelStyle: TextStyle(
|
||||
color: immichDarkThemePrimaryColor,
|
||||
),
|
||||
hintStyle: const TextStyle(
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
textSelectionTheme: TextSelectionThemeData(
|
||||
textSelectionTheme: const TextSelectionThemeData(
|
||||
cursorColor: immichDarkThemePrimaryColor,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -3,10 +3,10 @@ import 'package:immich_mobile/shared/models/store.dart';
|
||||
String sanitizeUrl(String url) {
|
||||
// Add schema if none is set
|
||||
final urlWithSchema =
|
||||
url.startsWith(RegExp(r"https?://")) ? url : "https://$url";
|
||||
url.trimLeft().startsWith(RegExp(r"https?://")) ? url : "https://$url";
|
||||
|
||||
// Remove trailing slash(es)
|
||||
return urlWithSchema.replaceFirst(RegExp(r"/+$"), "");
|
||||
return urlWithSchema.trimRight().replaceFirst(RegExp(r"/+$"), "");
|
||||
}
|
||||
|
||||
String? getServerUrl() {
|
||||
|
||||
Generated
-3
@@ -46,7 +46,6 @@ doc/CQMode.md
|
||||
doc/ChangePasswordDto.md
|
||||
doc/CheckExistingAssetsDto.md
|
||||
doc/CheckExistingAssetsResponseDto.md
|
||||
doc/CitiesFile.md
|
||||
doc/ClassificationConfig.md
|
||||
doc/Colorspace.md
|
||||
doc/CreateAlbumDto.md
|
||||
@@ -231,7 +230,6 @@ lib/model/bulk_ids_dto.dart
|
||||
lib/model/change_password_dto.dart
|
||||
lib/model/check_existing_assets_dto.dart
|
||||
lib/model/check_existing_assets_response_dto.dart
|
||||
lib/model/cities_file.dart
|
||||
lib/model/classification_config.dart
|
||||
lib/model/clip_config.dart
|
||||
lib/model/clip_mode.dart
|
||||
@@ -388,7 +386,6 @@ test/bulk_ids_dto_test.dart
|
||||
test/change_password_dto_test.dart
|
||||
test/check_existing_assets_dto_test.dart
|
||||
test/check_existing_assets_response_dto_test.dart
|
||||
test/cities_file_test.dart
|
||||
test/classification_config_test.dart
|
||||
test/clip_config_test.dart
|
||||
test/clip_mode_test.dart
|
||||
|
||||
Generated
+2
-2
@@ -98,6 +98,7 @@ Class | Method | HTTP request | Description
|
||||
*AssetApi* | [**downloadFile**](doc//AssetApi.md#downloadfile) | **POST** /asset/download/{id} |
|
||||
*AssetApi* | [**emptyTrash**](doc//AssetApi.md#emptytrash) | **POST** /asset/trash/empty |
|
||||
*AssetApi* | [**getAllAssets**](doc//AssetApi.md#getallassets) | **GET** /asset |
|
||||
*AssetApi* | [**getAllUserAssetsByDeviceId**](doc//AssetApi.md#getalluserassetsbydeviceid) | **GET** /asset/device/{deviceId} |
|
||||
*AssetApi* | [**getAssetById**](doc//AssetApi.md#getassetbyid) | **GET** /asset/assetById/{id} |
|
||||
*AssetApi* | [**getAssetSearchTerms**](doc//AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms |
|
||||
*AssetApi* | [**getAssetStatistics**](doc//AssetApi.md#getassetstatistics) | **GET** /asset/statistics |
|
||||
@@ -110,7 +111,7 @@ Class | Method | HTTP request | Description
|
||||
*AssetApi* | [**getRandom**](doc//AssetApi.md#getrandom) | **GET** /asset/random |
|
||||
*AssetApi* | [**getTimeBucket**](doc//AssetApi.md#gettimebucket) | **GET** /asset/time-bucket |
|
||||
*AssetApi* | [**getTimeBuckets**](doc//AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets |
|
||||
*AssetApi* | [**getUserAssetsByDeviceId**](doc//AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} |
|
||||
*AssetApi* | [**getUserAssetsByDeviceId**](doc//AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} | Use /asset/device/:deviceId instead - Remove in 1.92 release
|
||||
*AssetApi* | [**restoreAssets**](doc//AssetApi.md#restoreassets) | **POST** /asset/restore |
|
||||
*AssetApi* | [**restoreTrash**](doc//AssetApi.md#restoretrash) | **POST** /asset/trash/restore |
|
||||
*AssetApi* | [**runAssetJobs**](doc//AssetApi.md#runassetjobs) | **POST** /asset/jobs |
|
||||
@@ -243,7 +244,6 @@ Class | Method | HTTP request | Description
|
||||
- [ChangePasswordDto](doc//ChangePasswordDto.md)
|
||||
- [CheckExistingAssetsDto](doc//CheckExistingAssetsDto.md)
|
||||
- [CheckExistingAssetsResponseDto](doc//CheckExistingAssetsResponseDto.md)
|
||||
- [CitiesFile](doc//CitiesFile.md)
|
||||
- [ClassificationConfig](doc//ClassificationConfig.md)
|
||||
- [Colorspace](doc//Colorspace.md)
|
||||
- [CreateAlbumDto](doc//CreateAlbumDto.md)
|
||||
|
||||
Generated
+61
-5
@@ -16,6 +16,7 @@ Method | HTTP request | Description
|
||||
[**downloadFile**](AssetApi.md#downloadfile) | **POST** /asset/download/{id} |
|
||||
[**emptyTrash**](AssetApi.md#emptytrash) | **POST** /asset/trash/empty |
|
||||
[**getAllAssets**](AssetApi.md#getallassets) | **GET** /asset |
|
||||
[**getAllUserAssetsByDeviceId**](AssetApi.md#getalluserassetsbydeviceid) | **GET** /asset/device/{deviceId} |
|
||||
[**getAssetById**](AssetApi.md#getassetbyid) | **GET** /asset/assetById/{id} |
|
||||
[**getAssetSearchTerms**](AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms |
|
||||
[**getAssetStatistics**](AssetApi.md#getassetstatistics) | **GET** /asset/statistics |
|
||||
@@ -28,7 +29,7 @@ Method | HTTP request | Description
|
||||
[**getRandom**](AssetApi.md#getrandom) | **GET** /asset/random |
|
||||
[**getTimeBucket**](AssetApi.md#gettimebucket) | **GET** /asset/time-bucket |
|
||||
[**getTimeBuckets**](AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets |
|
||||
[**getUserAssetsByDeviceId**](AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} |
|
||||
[**getUserAssetsByDeviceId**](AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} | Use /asset/device/:deviceId instead - Remove in 1.92 release
|
||||
[**restoreAssets**](AssetApi.md#restoreassets) | **POST** /asset/restore |
|
||||
[**restoreTrash**](AssetApi.md#restoretrash) | **POST** /asset/trash/restore |
|
||||
[**runAssetJobs**](AssetApi.md#runassetjobs) | **POST** /asset/jobs |
|
||||
@@ -443,6 +444,63 @@ Name | Type | Description | Notes
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getAllUserAssetsByDeviceId**
|
||||
> List<String> getAllUserAssetsByDeviceId(deviceId)
|
||||
|
||||
|
||||
|
||||
Get all asset of a device that are in the database, ID only.
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = AssetApi();
|
||||
final deviceId = deviceId_example; // String |
|
||||
|
||||
try {
|
||||
final result = api_instance.getAllUserAssetsByDeviceId(deviceId);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling AssetApi->getAllUserAssetsByDeviceId: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**deviceId** | **String**| |
|
||||
|
||||
### Return type
|
||||
|
||||
**List<String>**
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getAssetById**
|
||||
> AssetResponseDto getAssetById(id, key)
|
||||
|
||||
@@ -1154,9 +1212,7 @@ Name | Type | Description | Notes
|
||||
# **getUserAssetsByDeviceId**
|
||||
> List<String> getUserAssetsByDeviceId(deviceId)
|
||||
|
||||
|
||||
|
||||
Get all asset of a device that are in the database, ID only.
|
||||
Use /asset/device/:deviceId instead - Remove in 1.92 release
|
||||
|
||||
### Example
|
||||
```dart
|
||||
@@ -1177,7 +1233,7 @@ import 'package:openapi/api.dart';
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = AssetApi();
|
||||
final deviceId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||
final deviceId = deviceId_example; // String |
|
||||
|
||||
try {
|
||||
final result = api_instance.getUserAssetsByDeviceId(deviceId);
|
||||
|
||||
Generated
-14
@@ -1,14 +0,0 @@
|
||||
# openapi.model.CitiesFile
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:openapi/api.dart';
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**citiesFileOverride** | [**CitiesFile**](CitiesFile.md) | |
|
||||
**enabled** | **bool** | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
Generated
-1
@@ -83,7 +83,6 @@ part 'model/cq_mode.dart';
|
||||
part 'model/change_password_dto.dart';
|
||||
part 'model/check_existing_assets_dto.dart';
|
||||
part 'model/check_existing_assets_response_dto.dart';
|
||||
part 'model/cities_file.dart';
|
||||
part 'model/classification_config.dart';
|
||||
part 'model/colorspace.dart';
|
||||
part 'model/create_album_dto.dart';
|
||||
|
||||
Generated
+58
-2
@@ -414,6 +414,62 @@ class AssetApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Get all asset of a device that are in the database, ID only.
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] deviceId (required):
|
||||
Future<Response> getAllUserAssetsByDeviceIdWithHttpInfo(String deviceId,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/asset/device/{deviceId}'
|
||||
.replaceAll('{deviceId}', deviceId);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Get all asset of a device that are in the database, ID only.
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] deviceId (required):
|
||||
Future<List<String>?> getAllUserAssetsByDeviceId(String deviceId,) async {
|
||||
final response = await getAllUserAssetsByDeviceIdWithHttpInfo(deviceId,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<String>') as List)
|
||||
.cast<String>()
|
||||
.toList();
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Get a single asset's information
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
@@ -1211,7 +1267,7 @@ class AssetApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Get all asset of a device that are in the database, ID only.
|
||||
/// Use /asset/device/:deviceId instead - Remove in 1.92 release
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
///
|
||||
@@ -1244,7 +1300,7 @@ class AssetApi {
|
||||
);
|
||||
}
|
||||
|
||||
/// Get all asset of a device that are in the database, ID only.
|
||||
/// Use /asset/device/:deviceId instead - Remove in 1.92 release
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
|
||||
Generated
-2
@@ -255,8 +255,6 @@ class ApiClient {
|
||||
return CheckExistingAssetsDto.fromJson(value);
|
||||
case 'CheckExistingAssetsResponseDto':
|
||||
return CheckExistingAssetsResponseDto.fromJson(value);
|
||||
case 'CitiesFile':
|
||||
return CitiesFileTypeTransformer().decode(value);
|
||||
case 'ClassificationConfig':
|
||||
return ClassificationConfig.fromJson(value);
|
||||
case 'Colorspace':
|
||||
|
||||
Generated
-3
@@ -73,9 +73,6 @@ String parameterToString(dynamic value) {
|
||||
if (value is CQMode) {
|
||||
return CQModeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is CitiesFile) {
|
||||
return CitiesFileTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is Colorspace) {
|
||||
return ColorspaceTypeTransformer().encode(value).toString();
|
||||
}
|
||||
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class CitiesFile {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const CitiesFile._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const cities15000 = CitiesFile._(r'cities15000');
|
||||
static const cities5000 = CitiesFile._(r'cities5000');
|
||||
static const cities1000 = CitiesFile._(r'cities1000');
|
||||
static const cities500 = CitiesFile._(r'cities500');
|
||||
|
||||
/// List of all possible values in this [enum][CitiesFile].
|
||||
static const values = <CitiesFile>[
|
||||
cities15000,
|
||||
cities5000,
|
||||
cities1000,
|
||||
cities500,
|
||||
];
|
||||
|
||||
static CitiesFile? fromJson(dynamic value) => CitiesFileTypeTransformer().decode(value);
|
||||
|
||||
static List<CitiesFile>? listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <CitiesFile>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = CitiesFile.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [CitiesFile] to String,
|
||||
/// and [decode] dynamic data back to [CitiesFile].
|
||||
class CitiesFileTypeTransformer {
|
||||
factory CitiesFileTypeTransformer() => _instance ??= const CitiesFileTypeTransformer._();
|
||||
|
||||
const CitiesFileTypeTransformer._();
|
||||
|
||||
String encode(CitiesFile data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a CitiesFile.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
CitiesFile? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'cities15000': return CitiesFile.cities15000;
|
||||
case r'cities5000': return CitiesFile.cities5000;
|
||||
case r'cities1000': return CitiesFile.cities1000;
|
||||
case r'cities500': return CitiesFile.cities500;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [CitiesFileTypeTransformer] instance.
|
||||
static CitiesFileTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
@@ -13,31 +13,25 @@ part of openapi.api;
|
||||
class SystemConfigReverseGeocodingDto {
|
||||
/// Returns a new [SystemConfigReverseGeocodingDto] instance.
|
||||
SystemConfigReverseGeocodingDto({
|
||||
required this.citiesFileOverride,
|
||||
required this.enabled,
|
||||
});
|
||||
|
||||
CitiesFile citiesFileOverride;
|
||||
|
||||
bool enabled;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SystemConfigReverseGeocodingDto &&
|
||||
other.citiesFileOverride == citiesFileOverride &&
|
||||
other.enabled == enabled;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(citiesFileOverride.hashCode) +
|
||||
(enabled.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'SystemConfigReverseGeocodingDto[citiesFileOverride=$citiesFileOverride, enabled=$enabled]';
|
||||
String toString() => 'SystemConfigReverseGeocodingDto[enabled=$enabled]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'citiesFileOverride'] = this.citiesFileOverride;
|
||||
json[r'enabled'] = this.enabled;
|
||||
return json;
|
||||
}
|
||||
@@ -50,7 +44,6 @@ class SystemConfigReverseGeocodingDto {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return SystemConfigReverseGeocodingDto(
|
||||
citiesFileOverride: CitiesFile.fromJson(json[r'citiesFileOverride'])!,
|
||||
enabled: mapValueOfType<bool>(json, r'enabled')!,
|
||||
);
|
||||
}
|
||||
@@ -99,7 +92,6 @@ class SystemConfigReverseGeocodingDto {
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'citiesFileOverride',
|
||||
'enabled',
|
||||
};
|
||||
}
|
||||
|
||||
Generated
+8
-1
@@ -58,6 +58,13 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// Get all asset of a device that are in the database, ID only.
|
||||
//
|
||||
//Future<List<String>> getAllUserAssetsByDeviceId(String deviceId) async
|
||||
test('test getAllUserAssetsByDeviceId', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// Get a single asset's information
|
||||
//
|
||||
//Future<AssetResponseDto> getAssetById(String id, { String key }) async
|
||||
@@ -120,7 +127,7 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// Get all asset of a device that are in the database, ID only.
|
||||
// Use /asset/device/:deviceId instead - Remove in 1.92 release
|
||||
//
|
||||
//Future<List<String>> getUserAssetsByDeviceId(String deviceId) async
|
||||
test('test getUserAssetsByDeviceId', () async {
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for CitiesFile
|
||||
void main() {
|
||||
|
||||
group('test CitiesFile', () {
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@@ -16,11 +16,6 @@ void main() {
|
||||
// final instance = SystemConfigReverseGeocodingDto();
|
||||
|
||||
group('test SystemConfigReverseGeocodingDto', () {
|
||||
// CitiesFile citiesFileOverride
|
||||
test('to test the property `citiesFileOverride`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool enabled
|
||||
test('to test the property `enabled`', () async {
|
||||
// TODO
|
||||
|
||||
Reference in New Issue
Block a user