mirror of https://github.com/gmbrax/Pilgrim.git
				
				
				
			
						commit
						ca14588a1d
					
				|  | @ -33,30 +33,30 @@ class EntryServiceMock(EntryService): | ||||||
|         } |         } | ||||||
|         self._next_id = 11 |         self._next_id = 11 | ||||||
| 
 | 
 | ||||||
|     # Métodos síncronos (mantidos para compatibilidade) |     # Synchronous methods (kept for compatibility) | ||||||
|     def create(self, travel_diary_id: int, title: str, text: str, date: str) -> Entry: |     def create(self, travel_diary_id: int, title: str, text: str, date: str) -> Entry: | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         new_entry = Entry(title, text, date, travel_diary_id, id=self._next_id) |         new_entry = Entry(title, text, date, travel_diary_id, id=self._next_id) | ||||||
|         self.mock_data[self._next_id] = new_entry |         self.mock_data[self._next_id] = new_entry | ||||||
|         self._next_id += 1 |         self._next_id += 1 | ||||||
|         return new_entry |         return new_entry | ||||||
| 
 | 
 | ||||||
|     def read_by_id(self, entry_id: int) -> Entry | None: |     def read_by_id(self, entry_id: int) -> Entry | None: | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         return self.mock_data.get(entry_id) |         return self.mock_data.get(entry_id) | ||||||
| 
 | 
 | ||||||
|     def read_all(self) -> List[Entry]: |     def read_all(self) -> List[Entry]: | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         return list(self.mock_data.values()) |         return list(self.mock_data.values()) | ||||||
| 
 | 
 | ||||||
|     def read_by_travel_diary_id(self, travel_diary_id: int) -> List[Entry]: |     def read_by_travel_diary_id(self, travel_diary_id: int) -> List[Entry]: | ||||||
|         """Versão síncrona - lê entradas por diário""" |         """Synchronous version - reads entries by diary""" | ||||||
|         return [entry for entry in self.mock_data.values() if entry.fk_travel_diary_id == travel_diary_id] |         return [entry for entry in self.mock_data.values() if entry.fk_travel_diary_id == travel_diary_id] | ||||||
| 
 | 
 | ||||||
|     def read_paginated(self, travel_diary_id: int, page: int = 1, page_size: int = 5) -> Tuple[List[Entry], int, int]: |     def read_paginated(self, travel_diary_id: int, page: int = 1, page_size: int = 5) -> Tuple[List[Entry], int, int]: | ||||||
|         """Versão síncrona - lê entradas paginadas por diário""" |         """Synchronous version - reads paginated entries by diary""" | ||||||
|         entries = self.read_by_travel_diary_id(travel_diary_id) |         entries = self.read_by_travel_diary_id(travel_diary_id) | ||||||
|         entries.sort(key=lambda x: x.id, reverse=True)  # Mais recentes primeiro |         entries.sort(key=lambda x: x.id, reverse=True)  # Most recent first | ||||||
|          |          | ||||||
|         total_entries = len(entries) |         total_entries = len(entries) | ||||||
|         total_pages = (total_entries + page_size - 1) // page_size |         total_pages = (total_entries + page_size - 1) // page_size | ||||||
|  | @ -69,7 +69,7 @@ class EntryServiceMock(EntryService): | ||||||
|         return page_entries, total_pages, total_entries |         return page_entries, total_pages, total_entries | ||||||
| 
 | 
 | ||||||
|     def update(self, entry_src: Entry, entry_dst: Entry) -> Entry | None: |     def update(self, entry_src: Entry, entry_dst: Entry) -> Entry | None: | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         item_to_update = self.mock_data.get(entry_src.id) |         item_to_update = self.mock_data.get(entry_src.id) | ||||||
|         if item_to_update: |         if item_to_update: | ||||||
|             item_to_update.title = entry_dst.title if entry_dst.title is not None else item_to_update.title |             item_to_update.title = entry_dst.title if entry_dst.title is not None else item_to_update.title | ||||||
|  | @ -83,41 +83,41 @@ class EntryServiceMock(EntryService): | ||||||
|         return None |         return None | ||||||
| 
 | 
 | ||||||
|     def delete(self, entry_src: Entry) -> Entry | None: |     def delete(self, entry_src: Entry) -> Entry | None: | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         return self.mock_data.pop(entry_src.id, None) |         return self.mock_data.pop(entry_src.id, None) | ||||||
| 
 | 
 | ||||||
|     # Métodos assíncronos (principais) |     # Async methods (main) | ||||||
|     async def async_create(self, travel_diary_id: int, title: str, text: str, date: str) -> Entry: |     async def async_create(self, travel_diary_id: int, title: str, text: str, date: str) -> Entry: | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.create(travel_diary_id, title, text, date) |         return self.create(travel_diary_id, title, text, date) | ||||||
| 
 | 
 | ||||||
|     async def async_read_by_id(self, entry_id: int) -> Entry | None: |     async def async_read_by_id(self, entry_id: int) -> Entry | None: | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.read_by_id(entry_id) |         return self.read_by_id(entry_id) | ||||||
| 
 | 
 | ||||||
|     async def async_read_all(self) -> List[Entry]: |     async def async_read_all(self) -> List[Entry]: | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.read_all() |         return self.read_all() | ||||||
| 
 | 
 | ||||||
|     async def async_read_by_travel_diary_id(self, travel_diary_id: int) -> List[Entry]: |     async def async_read_by_travel_diary_id(self, travel_diary_id: int) -> List[Entry]: | ||||||
|         """Versão assíncrona - lê entradas por diário""" |         """Async version - reads entries by diary""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.read_by_travel_diary_id(travel_diary_id) |         return self.read_by_travel_diary_id(travel_diary_id) | ||||||
| 
 | 
 | ||||||
|     async def async_read_paginated(self, travel_diary_id: int, page: int = 1, page_size: int = 5) -> Tuple[List[Entry], int, int]: |     async def async_read_paginated(self, travel_diary_id: int, page: int = 1, page_size: int = 5) -> Tuple[List[Entry], int, int]: | ||||||
|         """Versão assíncrona - lê entradas paginadas por diário""" |         """Async version - reads paginated entries by diary""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.read_paginated(travel_diary_id, page, page_size) |         return self.read_paginated(travel_diary_id, page, page_size) | ||||||
| 
 | 
 | ||||||
|     async def async_update(self, entry_src: Entry, entry_dst: Entry) -> Entry | None: |     async def async_update(self, entry_src: Entry, entry_dst: Entry) -> Entry | None: | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.update(entry_src, entry_dst) |         return self.update(entry_src, entry_dst) | ||||||
| 
 | 
 | ||||||
|     async def async_delete(self, entry_src: Entry) -> Entry | None: |     async def async_delete(self, entry_src: Entry) -> Entry | None: | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.delete(entry_src) |         return self.delete(entry_src) | ||||||
|  | @ -12,24 +12,24 @@ class TravelDiaryServiceMock(TravelDiaryService): | ||||||
|         } |         } | ||||||
|         self._next_id = 3 |         self._next_id = 3 | ||||||
| 
 | 
 | ||||||
|     # Métodos síncronos (originais) |     # Synchronous methods (original) | ||||||
|     def create(self, name: str): |     def create(self, name: str): | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         new_travel_diary = TravelDiary(id=self._next_id, name=name) |         new_travel_diary = TravelDiary(id=self._next_id, name=name) | ||||||
|         self.mock_data[self._next_id] = new_travel_diary |         self.mock_data[self._next_id] = new_travel_diary | ||||||
|         self._next_id += 1 |         self._next_id += 1 | ||||||
|         return new_travel_diary |         return new_travel_diary | ||||||
| 
 | 
 | ||||||
|     def read_by_id(self, travel_id: int): |     def read_by_id(self, travel_id: int): | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         return self.mock_data.get(travel_id) |         return self.mock_data.get(travel_id) | ||||||
| 
 | 
 | ||||||
|     def read_all(self): |     def read_all(self): | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         return list(self.mock_data.values()) |         return list(self.mock_data.values()) | ||||||
| 
 | 
 | ||||||
|     def update(self, travel_diary_id: int, name: str): |     def update(self, travel_diary_id: int, name: str): | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         item_to_update = self.mock_data.get(travel_diary_id) |         item_to_update = self.mock_data.get(travel_diary_id) | ||||||
|         if item_to_update: |         if item_to_update: | ||||||
|             item_to_update.name = name |             item_to_update.name = name | ||||||
|  | @ -37,31 +37,31 @@ class TravelDiaryServiceMock(TravelDiaryService): | ||||||
|         return None |         return None | ||||||
| 
 | 
 | ||||||
|     def delete(self, travel_diary_id: int): |     def delete(self, travel_diary_id: int): | ||||||
|         """Versão síncrona""" |         """Synchronous version""" | ||||||
|         return self.mock_data.pop(travel_diary_id, None) |         return self.mock_data.pop(travel_diary_id, None) | ||||||
| 
 | 
 | ||||||
|     # Métodos assíncronos (novos) |     # Async methods (new) | ||||||
|     async def async_create(self, name: str): |     async def async_create(self, name: str): | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.create(name) |         return self.create(name) | ||||||
| 
 | 
 | ||||||
|     async def async_read_by_id(self, travel_id: int): |     async def async_read_by_id(self, travel_id: int): | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.read_by_id(travel_id) |         return self.read_by_id(travel_id) | ||||||
| 
 | 
 | ||||||
|     async def async_read_all(self): |     async def async_read_all(self): | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.read_all() |         return self.read_all() | ||||||
| 
 | 
 | ||||||
|     async def async_update(self, travel_diary_id: int, name: str): |     async def async_update(self, travel_diary_id: int, name: str): | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.update(travel_diary_id, name) |         return self.update(travel_diary_id, name) | ||||||
| 
 | 
 | ||||||
|     async def async_delete(self, travel_diary_id: int): |     async def async_delete(self, travel_diary_id: int): | ||||||
|         """Versão assíncrona""" |         """Async version""" | ||||||
|         await asyncio.sleep(0.01)  # Simula I/O |         await asyncio.sleep(0.01)  # Simulates I/O | ||||||
|         return self.delete(travel_diary_id) |         return self.delete(travel_diary_id) | ||||||
|  | @ -5,7 +5,7 @@ from textual.widgets import Header, Footer, Button, Label, TextArea | ||||||
| from textual.containers import Container | from textual.containers import Container | ||||||
| 
 | 
 | ||||||
| class AboutScreen(Screen[bool]): | class AboutScreen(Screen[bool]): | ||||||
|     """Tela para exibir informações sobre a aplicação.""" |     """Screen to display application information.""" | ||||||
| 
 | 
 | ||||||
|     TITLE = "Pilgrim - About" |     TITLE = "Pilgrim - About" | ||||||
| 
 | 
 | ||||||
|  | @ -51,20 +51,20 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||||
|         yield self.footer |         yield self.footer | ||||||
| 
 | 
 | ||||||
|     def on_button_pressed(self, event: Button.Pressed) -> None: |     def on_button_pressed(self, event: Button.Pressed) -> None: | ||||||
|         """Lida com os cliques dos botões.""" |         """Handles button clicks.""" | ||||||
|         if "about-close-button" in event.button.classes: |         if "about-close-button" in event.button.classes: | ||||||
|             self.dismiss(False) |             self.dismiss(False) | ||||||
|         elif "about-info-button" in event.button.classes: |         elif "about-info-button" in event.button.classes: | ||||||
|             self.notify("Mais informações seriam exibidas aqui!", title="Info") |             self.notify("More information would be displayed here!", title="Info") | ||||||
| 
 | 
 | ||||||
|     def action_dismiss(self, **kwargs) -> None: |     def action_dismiss(self, **kwargs) -> None: | ||||||
|         """Fecha o about box usando dismiss. |         """Closes the about box using dismiss. | ||||||
|         :param **kwargs: |         :param **kwargs: | ||||||
|         """ |         """ | ||||||
|         self.dismiss(False) |         self.dismiss(False) | ||||||
| 
 | 
 | ||||||
|     def on_key(self, event) -> None: |     def on_key(self, event) -> None: | ||||||
|         """Intercepta teclas específicas.""" |         """Intercepts specific keys.""" | ||||||
|         if event.key == "escape": |         if event.key == "escape": | ||||||
|             self.dismiss(False) |             self.dismiss(False) | ||||||
|             event.prevent_default() |             event.prevent_default() | ||||||
|  |  | ||||||
|  | @ -58,31 +58,31 @@ class DiaryListScreen(Screen): | ||||||
|         yield self.footer |         yield self.footer | ||||||
| 
 | 
 | ||||||
|     def on_mount(self) -> None: |     def on_mount(self) -> None: | ||||||
|         # Usa versão síncrona para o mount inicial |         # Uses synchronous version for initial mount | ||||||
|         self.refresh_diaries() |         self.refresh_diaries() | ||||||
|         self.update_buttons_state() |         self.update_buttons_state() | ||||||
| 
 | 
 | ||||||
|     def refresh_diaries(self): |     def refresh_diaries(self): | ||||||
|         """Versão síncrona do refresh""" |         """Synchronous version of refresh""" | ||||||
|         try: |         try: | ||||||
|             service_manager = self.app.service_manager |             service_manager = self.app.service_manager | ||||||
|             travel_diary_service = service_manager.get_travel_diary_service() |             travel_diary_service = service_manager.get_travel_diary_service() | ||||||
| 
 | 
 | ||||||
|             # Usa método síncrono |             # Uses synchronous method | ||||||
|             diaries = travel_diary_service.read_all() |             diaries = travel_diary_service.read_all() | ||||||
| 
 | 
 | ||||||
|             # Salva o estado atual |             # Saves current state | ||||||
|             current_diary_id = None |             current_diary_id = None | ||||||
|             if (self.selected_diary_index is not None and |             if (self.selected_diary_index is not None and | ||||||
|                     self.selected_diary_index in self.diary_id_map): |                     self.selected_diary_index in self.diary_id_map): | ||||||
|                 current_diary_id = self.diary_id_map[self.selected_diary_index] |                 current_diary_id = self.diary_id_map[self.selected_diary_index] | ||||||
| 
 | 
 | ||||||
|             # Limpa e reconstrói |             # Clears and rebuilds | ||||||
|             self.diary_list.clear_options() |             self.diary_list.clear_options() | ||||||
|             self.diary_id_map = {} |             self.diary_id_map = {} | ||||||
| 
 | 
 | ||||||
|             if not diaries: |             if not diaries: | ||||||
|                 self.diary_list.add_option("[dim]Nenhum diário encontrado. Pressione 'N' para criar um novo![/dim]") |                 self.diary_list.add_option("[dim]No diaries found. Press 'N' to create a new one![/dim]") | ||||||
|                 self.selected_diary_index = None |                 self.selected_diary_index = None | ||||||
|             else: |             else: | ||||||
|                 new_selected_index = 0 |                 new_selected_index = 0 | ||||||
|  | @ -91,33 +91,33 @@ class DiaryListScreen(Screen): | ||||||
|                     self.diary_id_map[index] = diary.id |                     self.diary_id_map[index] = diary.id | ||||||
|                     self.diary_list.add_option(f"[b]{diary.name}[/b]\n[dim]ID: {diary.id}[/dim]") |                     self.diary_list.add_option(f"[b]{diary.name}[/b]\n[dim]ID: {diary.id}[/dim]") | ||||||
| 
 | 
 | ||||||
|                     # Mantém a seleção se possível |                     # Maintains selection if possible | ||||||
|                     if current_diary_id and diary.id == current_diary_id: |                     if current_diary_id and diary.id == current_diary_id: | ||||||
|                         new_selected_index = index |                         new_selected_index = index | ||||||
| 
 | 
 | ||||||
|                 self.selected_diary_index = new_selected_index |                 self.selected_diary_index = new_selected_index | ||||||
| 
 | 
 | ||||||
|                 # Atualiza o highlight |                 # Updates highlight | ||||||
|                 self.set_timer(0.05, lambda: self._update_highlight(new_selected_index)) |                 self.set_timer(0.05, lambda: self._update_highlight(new_selected_index)) | ||||||
| 
 | 
 | ||||||
|             # Força refresh visual |             # Forces visual refresh | ||||||
|             self.diary_list.refresh() |             self.diary_list.refresh() | ||||||
|             self.update_buttons_state() |             self.update_buttons_state() | ||||||
| 
 | 
 | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             self.notify(f"Erro ao carregar diários: {str(e)}") |             self.notify(f"Error loading diaries: {str(e)}") | ||||||
| 
 | 
 | ||||||
|     def _update_highlight(self, index: int): |     def _update_highlight(self, index: int): | ||||||
|         """Atualiza o highlight do OptionList""" |         """Updates the OptionList highlight""" | ||||||
|         try: |         try: | ||||||
|             if index < len(self.diary_list.options): |             if index < len(self.diary_list.options): | ||||||
|                 self.diary_list.highlighted = index |                 self.diary_list.highlighted = index | ||||||
|                 self.diary_list.refresh() |                 self.diary_list.refresh() | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             self.notify(f"Erro ao atualizar highlight: {str(e)}") |             self.notify(f"Error updating highlight: {str(e)}") | ||||||
| 
 | 
 | ||||||
|     async def async_refresh_diaries(self): |     async def async_refresh_diaries(self): | ||||||
|         """Versão assíncrona do refresh""" |         """Async version of refresh""" | ||||||
|         if self.is_refreshing: |         if self.is_refreshing: | ||||||
|             return |             return | ||||||
| 
 | 
 | ||||||
|  | @ -127,21 +127,21 @@ class DiaryListScreen(Screen): | ||||||
|             service_manager = self.app.service_manager |             service_manager = self.app.service_manager | ||||||
|             travel_diary_service = service_manager.get_travel_diary_service() |             travel_diary_service = service_manager.get_travel_diary_service() | ||||||
| 
 | 
 | ||||||
|             # Usa método assíncrono |             # Uses async method | ||||||
|             diaries = await travel_diary_service.async_read_all() |             diaries = await travel_diary_service.async_read_all() | ||||||
| 
 | 
 | ||||||
|             # Salva o estado atual |             # Saves current state | ||||||
|             current_diary_id = None |             current_diary_id = None | ||||||
|             if (self.selected_diary_index is not None and |             if (self.selected_diary_index is not None and | ||||||
|                     self.selected_diary_index in self.diary_id_map): |                     self.selected_diary_index in self.diary_id_map): | ||||||
|                 current_diary_id = self.diary_id_map[self.selected_diary_index] |                 current_diary_id = self.diary_id_map[self.selected_diary_index] | ||||||
| 
 | 
 | ||||||
|             # Limpa e reconstrói |             # Clears and rebuilds | ||||||
|             self.diary_list.clear_options() |             self.diary_list.clear_options() | ||||||
|             self.diary_id_map = {} |             self.diary_id_map = {} | ||||||
| 
 | 
 | ||||||
|             if not diaries: |             if not diaries: | ||||||
|                 self.diary_list.add_option("[dim]Nenhum diário encontrado. Pressione 'N' para criar um novo![/dim]") |                 self.diary_list.add_option("[dim]No diaries found. Press 'N' to create a new one![/dim]") | ||||||
|                 self.selected_diary_index = None |                 self.selected_diary_index = None | ||||||
|             else: |             else: | ||||||
|                 new_selected_index = 0 |                 new_selected_index = 0 | ||||||
|  | @ -160,12 +160,12 @@ class DiaryListScreen(Screen): | ||||||
|             self.update_buttons_state() |             self.update_buttons_state() | ||||||
| 
 | 
 | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             self.notify(f"Erro ao carregar diários: {str(e)}") |             self.notify(f"Error loading diaries: {str(e)}") | ||||||
|         finally: |         finally: | ||||||
|             self.is_refreshing = False |             self.is_refreshing = False | ||||||
| 
 | 
 | ||||||
|     def on_option_list_option_highlighted(self, event: OptionList.OptionHighlighted) -> None: |     def on_option_list_option_highlighted(self, event: OptionList.OptionHighlighted) -> None: | ||||||
|         """Handle quando uma opção é destacada""" |         """Handle when an option is highlighted""" | ||||||
|         if self.diary_id_map and event.option_index in self.diary_id_map: |         if self.diary_id_map and event.option_index in self.diary_id_map: | ||||||
|             self.selected_diary_index = event.option_index |             self.selected_diary_index = event.option_index | ||||||
|         else: |         else: | ||||||
|  | @ -174,7 +174,7 @@ class DiaryListScreen(Screen): | ||||||
|         self.update_buttons_state() |         self.update_buttons_state() | ||||||
| 
 | 
 | ||||||
|     def on_option_list_option_selected(self, event: OptionList.OptionSelected) -> None: |     def on_option_list_option_selected(self, event: OptionList.OptionSelected) -> None: | ||||||
|         """Handle quando uma opção é selecionada""" |         """Handle when an option is selected""" | ||||||
|         if self.diary_id_map and event.option_index in self.diary_id_map: |         if self.diary_id_map and event.option_index in self.diary_id_map: | ||||||
|             self.selected_diary_index = event.option_index |             self.selected_diary_index = event.option_index | ||||||
|             self.action_open_diary() |             self.action_open_diary() | ||||||
|  | @ -184,7 +184,7 @@ class DiaryListScreen(Screen): | ||||||
|         self.update_buttons_state() |         self.update_buttons_state() | ||||||
| 
 | 
 | ||||||
|     def update_buttons_state(self): |     def update_buttons_state(self): | ||||||
|         """Atualiza o estado dos botões""" |         """Updates button states""" | ||||||
|         has_selection = (self.selected_diary_index is not None and |         has_selection = (self.selected_diary_index is not None and | ||||||
|                          self.selected_diary_index in self.diary_id_map) |                          self.selected_diary_index in self.diary_id_map) | ||||||
| 
 | 
 | ||||||
|  | @ -192,7 +192,7 @@ class DiaryListScreen(Screen): | ||||||
|         self.open_diary.disabled = not has_selection |         self.open_diary.disabled = not has_selection | ||||||
| 
 | 
 | ||||||
|     def on_button_pressed(self, event: Button.Pressed) -> None: |     def on_button_pressed(self, event: Button.Pressed) -> None: | ||||||
|         """Handle cliques nos botões""" |         """Handle button clicks""" | ||||||
|         button_id = event.button.id |         button_id = event.button.id | ||||||
| 
 | 
 | ||||||
|         if button_id == "new_diary": |         if button_id == "new_diary": | ||||||
|  | @ -203,7 +203,7 @@ class DiaryListScreen(Screen): | ||||||
|             self.action_open_diary() |             self.action_open_diary() | ||||||
| 
 | 
 | ||||||
|     def action_new_diary(self): |     def action_new_diary(self): | ||||||
|         """Ação para criar novo diário""" |         """Action to create new diary""" | ||||||
|         self.app.push_screen(NewDiaryModal(),self._on_new_diary_submitted) |         self.app.push_screen(NewDiaryModal(),self._on_new_diary_submitted) | ||||||
| 
 | 
 | ||||||
|     def _on_new_diary_submitted(self,result): |     def _on_new_diary_submitted(self,result): | ||||||
|  | @ -231,7 +231,7 @@ class DiaryListScreen(Screen): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def action_edit_selected_diary(self): |     def action_edit_selected_diary(self): | ||||||
|         """Ação para editar diário selecionado""" |         """Action to edit selected diary""" | ||||||
|         if self.selected_diary_index is not None: |         if self.selected_diary_index is not None: | ||||||
|             diary_id = self.diary_id_map.get(self.selected_diary_index) |             diary_id = self.diary_id_map.get(self.selected_diary_index) | ||||||
|             if diary_id: |             if diary_id: | ||||||
|  | @ -240,10 +240,10 @@ class DiaryListScreen(Screen): | ||||||
|                     self._on_edited_diary_name_submitted |                     self._on_edited_diary_name_submitted | ||||||
|                 ) |                 ) | ||||||
|         else: |         else: | ||||||
|             self.notify("Selecione um diário para editar") |             self.notify("Select a diary to edit") | ||||||
| 
 | 
 | ||||||
|     def action_open_diary(self): |     def action_open_diary(self): | ||||||
|         """Ação para abrir diário selecionado""" |         """Action to open selected diary""" | ||||||
|         if self.selected_diary_index is not None: |         if self.selected_diary_index is not None: | ||||||
|             diary_id = self.diary_id_map.get(self.selected_diary_index) |             diary_id = self.diary_id_map.get(self.selected_diary_index) | ||||||
|             if diary_id: |             if diary_id: | ||||||
|  | @ -252,44 +252,48 @@ class DiaryListScreen(Screen): | ||||||
|             else: |             else: | ||||||
|                 self.notify("Invalid diary ID") |                 self.notify("Invalid diary ID") | ||||||
|         else: |         else: | ||||||
|             self.notify("Selecione um diário para abrir") |             self.notify("Select a diary to open") | ||||||
| 
 | 
 | ||||||
|     def _on_edited_diary_name_submitted(self, result: Optional[Tuple[int, str]]) -> None: |     def _on_edited_diary_name_submitted(self, result: Optional[Tuple[int, str]]) -> None: | ||||||
|         """Callback após edição do diário""" |         """Callback after diary editing""" | ||||||
|         if result: |         if result: | ||||||
|             diary_id, name = result |             diary_id, name = result | ||||||
|             self.notify(f"Atualizando diário ID {diary_id} para '{name}'...") |             self.notify(f"Updating diary ID {diary_id} to '{name}'...") | ||||||
|             # Agenda a atualização assíncrona |             # Schedules async update | ||||||
|             self.call_later(self._async_update_diary, diary_id, name) |             self.call_later(self._async_update_diary, diary_id, name) | ||||||
|         else: |         else: | ||||||
|             self.notify("Edição cancelada") |             self.notify("Edit canceled") | ||||||
| 
 | 
 | ||||||
|     async def _async_update_diary(self, diary_id: int, name: str): |     async def _async_update_diary(self, diary_id: int, name: str): | ||||||
|         """Atualiza o diário de forma assíncrona""" |         """Updates the diary asynchronously""" | ||||||
|         try: |         try: | ||||||
|             service = self.app.service_manager.get_travel_diary_service() |             service = self.app.service_manager.get_travel_diary_service() | ||||||
|             updated_diary = await service.async_update(diary_id, name) |             updated_diary = await service.async_update(diary_id, name) | ||||||
| 
 | 
 | ||||||
|             if updated_diary: |             if updated_diary: | ||||||
|                 self.notify(f"Diário '{name}' atualizado!") |                 self.notify(f"Diary '{name}' updated!") | ||||||
|                 # Força refresh após a atualização |                 # Forces refresh after update | ||||||
|                 await self.async_refresh_diaries() |                 await self.async_refresh_diaries() | ||||||
|             else: |             else: | ||||||
|                 self.notify("Erro: Diário não encontrado") |                 self.notify("Error: Diary not found") | ||||||
| 
 | 
 | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             self.notify(f"Erro ao atualizar: {str(e)}") |             self.notify(f"Error updating: {str(e)}") | ||||||
| 
 | 
 | ||||||
|     def action_force_refresh(self): |     def action_force_refresh(self): | ||||||
|         """Força refresh manual""" |         """Forces manual refresh""" | ||||||
|         self.notify("Forçando refresh...") |         self.notify("Forcing refresh...") | ||||||
|         # Tenta ambas as versões |         # Tries both versions | ||||||
|         self.refresh_diaries()  # Síncrona |         self.refresh_diaries()  # Synchronous | ||||||
|         self.call_later(self.async_refresh_diaries)  # Assíncrona |         self.call_later(self.async_refresh_diaries)  # Asynchronous | ||||||
| 
 | 
 | ||||||
|     def action_open_selected_diary(self): |     def action_open_selected_diary(self): | ||||||
|         """Ação do binding ENTER""" |         """Action for ENTER binding""" | ||||||
|         self.action_open_diary() |         self.action_open_diary() | ||||||
| 
 | 
 | ||||||
|     def action_about_cmd(self): |     def action_about_cmd(self): | ||||||
|         self.app.push_screen(AboutScreen()) |         self.app.push_screen(AboutScreen()) | ||||||
|  | 
 | ||||||
|  |     def action_quit(self): | ||||||
|  |         """Action to quit the application""" | ||||||
|  |         self.app.exit() | ||||||
|  | @ -6,29 +6,28 @@ from textual.widgets import Label, Input, Button | ||||||
| 
 | 
 | ||||||
| class EditDiaryModal(ModalScreen[tuple[int,str]]): | class EditDiaryModal(ModalScreen[tuple[int,str]]): | ||||||
|     BINDINGS = [ |     BINDINGS = [ | ||||||
|         ("escape", "cancel", "Cancelar"), |         ("escape", "cancel", "Cancel"), | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|     def __init__(self, diary_id: int): |     def __init__(self, diary_id: int): | ||||||
|         super().__init__() |         super().__init__() | ||||||
|         self.diary_id = diary_id |         self.diary_id = diary_id | ||||||
|         self.current_diary_name = self.app.service_manager.get_travel_diary_service().read_by_id(self.diary_id).name |         self.current_diary_name = self.app.service_manager.get_travel_diary_service().read_by_id(self.diary_id).name | ||||||
|         self.name_input = Input(value=self.current_diary_name, id="edit_diary_name_input",classes="EditDiaryModal-NameInput") |         self.name_input = Input(value=self.current_diary_name, id="edit_diary_name_input", classes="EditDiaryModal-NameInput") | ||||||
| 
 | 
 | ||||||
|     def compose(self) -> ComposeResult: |     def compose(self) -> ComposeResult: | ||||||
|         with Vertical(id="edit_diary_dialog", classes="EditDiaryModal-Dialog"): |         with Vertical(id="edit_diary_dialog", classes="EditDiaryModal-Dialog"): | ||||||
|             yield Label(f"Editar Diário: {self.current_diary_name}", classes="EditDiaryModal-Title") |             yield Label("Edit Diary", classes="EditDiaryModal-Title") | ||||||
|             yield Label("Novo Nome do Diário:") |             yield Label("New Diary Name:") | ||||||
|             yield self.name_input |             yield self.name_input | ||||||
|             with Horizontal(classes="dialog-buttons"): |             with Horizontal(classes="EditDiaryModal-ButtonsContainer"): | ||||||
|                 yield Button("Salvar", variant="primary", id="save_diary_button") |                 yield Button("Save", variant="primary", id="save_diary_button", classes="EditDiaryModal-SaveButton") | ||||||
|                 yield Button("Cancelar", variant="default", id="cancel_button") |                 yield Button("Cancel", variant="default", id="cancel_button", classes="EditDiaryModal-CancelButton") | ||||||
| 
 | 
 | ||||||
|     def on_mount(self) -> None: |     def on_mount(self) -> None: | ||||||
|         """Foca no campo de entrada e move o cursor para o final do texto.""" |         """Focuses on the input field and moves cursor to the end of text.""" | ||||||
|         self.name_input.focus() |         self.name_input.focus() | ||||||
|         self.name_input.cursor_position = len(self.name_input.value) |         self.name_input.cursor_position = len(self.name_input.value) | ||||||
|         # REMOVIDA A LINHA QUE CAUSA O ERRO: self.name_input.select_text() |  | ||||||
| 
 | 
 | ||||||
|     def on_button_pressed(self, event: Button.Pressed) -> None: |     def on_button_pressed(self, event: Button.Pressed) -> None: | ||||||
|         if event.button.id == "save_diary_button": |         if event.button.id == "save_diary_button": | ||||||
|  | @ -36,10 +35,10 @@ class EditDiaryModal(ModalScreen[tuple[int,str]]): | ||||||
|             if new_diary_name and new_diary_name != self.current_diary_name: |             if new_diary_name and new_diary_name != self.current_diary_name: | ||||||
|                 self.dismiss((self.diary_id, new_diary_name)) |                 self.dismiss((self.diary_id, new_diary_name)) | ||||||
|             elif new_diary_name == self.current_diary_name: |             elif new_diary_name == self.current_diary_name: | ||||||
|                 self.notify("Nenhuma alteração feita.", severity="warning") |                 self.notify("No changes made.", severity="warning") | ||||||
|                 self.dismiss(None) |                 self.dismiss(None) | ||||||
|             else: |             else: | ||||||
|                 self.notify("O nome do diário não pode estar vazio.", severity="warning") |                 self.notify("Diary name cannot be empty.", severity="warning") | ||||||
|                 self.name_input.focus() |                 self.name_input.focus() | ||||||
|         elif event.button.id == "cancel_button": |         elif event.button.id == "cancel_button": | ||||||
|             self.dismiss(None) |             self.dismiss(None) | ||||||
|  |  | ||||||
|  | @ -14,21 +14,20 @@ from pilgrim.ui.screens.rename_entry_modal import RenameEntryModal | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class EditEntryScreen(Screen): | class EditEntryScreen(Screen): | ||||||
|     TITLE = "Pilgrim - Edit Entry" |     TITLE = "Pilgrim - Edit" | ||||||
| 
 | 
 | ||||||
|     BINDINGS = [ |     BINDINGS = [ | ||||||
|         Binding("ctrl+s", "save", "Save"), |         Binding("ctrl+s", "save", "Save"), | ||||||
|         Binding("ctrl+n", "next_entry", "Next/New Entry"), |         Binding("ctrl+n", "next_entry", "Next/New Entry"), | ||||||
|         Binding("ctrl+b", "prev_entry", "Previous Entry"), |         Binding("ctrl+b", "prev_entry", "Previous Entry"), | ||||||
|         Binding("ctrl+r", "rename_entry", "Rename Entry"), |         Binding("ctrl+r", "rename_entry", "Rename Entry"), | ||||||
|         Binding("escape", "back_to_list", "Back to List"), |         Binding("escape", "back_to_list", "Back to List") | ||||||
|         Binding("r", "force_refresh", "Force refresh"), |  | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|     def __init__(self, diary_id: int = 1): |     def __init__(self, diary_id: int = 1): | ||||||
|         super().__init__() |         super().__init__() | ||||||
|         self.diary_id = diary_id |         self.diary_id = diary_id | ||||||
|         self.diary_name = "Unknown Diary" |         self.diary_name = f"Diary {diary_id}"  # Use a better default name | ||||||
|         self.current_entry_index = 0 |         self.current_entry_index = 0 | ||||||
|         self.entries: List[Entry] = [] |         self.entries: List[Entry] = [] | ||||||
|         self.is_new_entry = False |         self.is_new_entry = False | ||||||
|  | @ -81,8 +80,7 @@ class EditEntryScreen(Screen): | ||||||
|         """Called when the screen is mounted""" |         """Called when the screen is mounted""" | ||||||
|         # First update diary info, then refresh entries |         # First update diary info, then refresh entries | ||||||
|         self.update_diary_info() |         self.update_diary_info() | ||||||
|         # Use a small delay to ensure diary info is loaded before refreshing entries |         self.refresh_entries() | ||||||
|         self.set_timer(0.1, self.refresh_entries) |  | ||||||
| 
 | 
 | ||||||
|     def update_diary_info(self): |     def update_diary_info(self): | ||||||
|         """Updates diary information""" |         """Updates diary information""" | ||||||
|  | @ -94,11 +92,27 @@ class EditEntryScreen(Screen): | ||||||
|             if diary: |             if diary: | ||||||
|                 self.diary_name = diary.name |                 self.diary_name = diary.name | ||||||
|                 self.diary_info.update(f"Diary: {self.diary_name}") |                 self.diary_info.update(f"Diary: {self.diary_name}") | ||||||
|                 self.notify(f"Loaded diary: {self.diary_name}") |  | ||||||
|             else: |             else: | ||||||
|                 self.notify(f"Diary with ID {self.diary_id} not found") |                 # If diary not found, try to get a default name | ||||||
|  |                 self.diary_name = f"Diary {self.diary_id}" | ||||||
|  |                 self.diary_info.update(f"Diary: {self.diary_name}") | ||||||
|  |                 self.notify(f"Diary {self.diary_id} not found, using default name") | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|  |             # If there's an error, use a default name but don't break the app | ||||||
|  |             self.diary_name = f"Diary {self.diary_id}" | ||||||
|  |             self.diary_info.update(f"Diary: {self.diary_name}") | ||||||
|             self.notify(f"Error loading diary info: {str(e)}") |             self.notify(f"Error loading diary info: {str(e)}") | ||||||
|  |          | ||||||
|  |         # Always ensure the diary info is updated | ||||||
|  |         self._ensure_diary_info_updated() | ||||||
|  | 
 | ||||||
|  |     def _ensure_diary_info_updated(self): | ||||||
|  |         """Ensures the diary info widget is always updated with current diary name""" | ||||||
|  |         try: | ||||||
|  |             self.diary_info.update(f"Diary: {self.diary_name}") | ||||||
|  |         except Exception as e: | ||||||
|  |             # If even this fails, at least try to show something | ||||||
|  |             self.diary_info.update(f"Diary: {self.diary_id}") | ||||||
| 
 | 
 | ||||||
|     def refresh_entries(self): |     def refresh_entries(self): | ||||||
|         """Synchronous version of refresh""" |         """Synchronous version of refresh""" | ||||||
|  | @ -124,6 +138,9 @@ class EditEntryScreen(Screen): | ||||||
| 
 | 
 | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             self.notify(f"Error loading entries: {str(e)}") |             self.notify(f"Error loading entries: {str(e)}") | ||||||
|  |          | ||||||
|  |         # Ensure diary info is updated even if entries fail to load | ||||||
|  |         self._ensure_diary_info_updated() | ||||||
| 
 | 
 | ||||||
|     async def async_refresh_entries(self): |     async def async_refresh_entries(self): | ||||||
|         """Asynchronous version of refresh""" |         """Asynchronous version of refresh""" | ||||||
|  | @ -178,7 +195,7 @@ class EditEntryScreen(Screen): | ||||||
|                 self._update_status_indicator("New", "new") |                 self._update_status_indicator("New", "new") | ||||||
|         else: |         else: | ||||||
|             current_entry = self.entries[self.current_entry_index] |             current_entry = self.entries[self.current_entry_index] | ||||||
|             entry_text = f"Entry: ({self.current_entry_index + 1}/{len(self.entries)}) {current_entry.title}" |             entry_text = f"Entry: \\[{self.current_entry_index + 1}/{len(self.entries)}] {current_entry.title}" | ||||||
|             self.entry_info.update(entry_text) |             self.entry_info.update(entry_text) | ||||||
|             self._update_status_indicator("Saved", "saved") |             self._update_status_indicator("Saved", "saved") | ||||||
| 
 | 
 | ||||||
|  | @ -198,10 +215,6 @@ class EditEntryScreen(Screen): | ||||||
|     def _update_entry_display(self): |     def _update_entry_display(self): | ||||||
|         """Updates the display of the current entry""" |         """Updates the display of the current entry""" | ||||||
|         if not self.entries and not self.is_new_entry: |         if not self.entries and not self.is_new_entry: | ||||||
|             # Ensure diary name is loaded |  | ||||||
|             if self.diary_name == "Unknown Diary": |  | ||||||
|                 self.update_diary_info() |  | ||||||
|              |  | ||||||
|             self.text_entry.text = f"No entries found for diary '{self.diary_name}'\n\nPress Ctrl+N to create a new entry." |             self.text_entry.text = f"No entries found for diary '{self.diary_name}'\n\nPress Ctrl+N to create a new entry." | ||||||
|             self.text_entry.read_only = True |             self.text_entry.read_only = True | ||||||
|             self._original_content = self.text_entry.text |             self._original_content = self.text_entry.text | ||||||
|  |  | ||||||
|  | @ -27,17 +27,17 @@ class NewDiaryModal(ModalScreen[str]): | ||||||
|           self.name_input.focus() |           self.name_input.focus() | ||||||
| 
 | 
 | ||||||
|     def on_button_pressed(self, event: Button.Pressed) -> None: |     def on_button_pressed(self, event: Button.Pressed) -> None: | ||||||
|         """Lida com os cliques dos botões.""" |         """Handles button clicks.""" | ||||||
|         if event.button.id == "create_diary_button": |         if event.button.id == "create_diary_button": | ||||||
|             diary_name = self.name_input.value.strip() |             diary_name = self.name_input.value.strip() | ||||||
|             if diary_name: |             if diary_name: | ||||||
|                 self.dismiss(diary_name) |                 self.dismiss(diary_name) | ||||||
|             else: |             else: | ||||||
|                 self.notify("O nome do diário não pode estar vazio.", severity="warning") |                 self.notify("Diary name cannot be empty.", severity="warning") | ||||||
|                 self.name_input.focus() |                 self.name_input.focus() | ||||||
|         elif event.button.id == "cancel_button": |         elif event.button.id == "cancel_button": | ||||||
|             self.dismiss("") |             self.dismiss("") | ||||||
| 
 | 
 | ||||||
|     def action_cancel(self) -> None: |     def action_cancel(self) -> None: | ||||||
|         """Ação para cancelar a modal.""" |         """Action to cancel the modal.""" | ||||||
|         self.dismiss("") |         self.dismiss("") | ||||||
|  | @ -3,175 +3,7 @@ Screen { | ||||||
|     background: $surface-darken-1; |     background: $surface-darken-1; | ||||||
|     align: center middle; |     align: center middle; | ||||||
| } | } | ||||||
| .DiaryListScreen-DiaryListContainer { |  | ||||||
|     height: 1fr; |  | ||||||
|     width: 100%; |  | ||||||
|     layout: vertical; |  | ||||||
|     align: center top; /* Alinha no topo para seguir o wireframe */ |  | ||||||
|     padding: 2 4; /* Mais espaço nas laterais */ |  | ||||||
|     background: $surface; /* Removendo aquamarine para ficar mais limpo */ |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| /* A lista de diários - área principal como no wireframe */ |  | ||||||
| .DiaryListScreen-DiaryListOptions { |  | ||||||
|     border: round $primary-lighten-2; |  | ||||||
|     background: $surface; |  | ||||||
|     width: 75%; /* Largura generosa como no wireframe */ |  | ||||||
|     height: 72%; /* Ocupa o espaço disponível */ |  | ||||||
|     margin: 2 0; /* Margem vertical para separar dos outros elementos */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .DiaryListScreen-DiaryListOptions:focus { |  | ||||||
|     border: round $primary; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* O contêiner dos botões - logo abaixo da lista */ |  | ||||||
| .DiaryListScreen-ButtonsGrid { |  | ||||||
|     layout: horizontal; |  | ||||||
|     align: center middle; |  | ||||||
|     width: 79%; /* Mesma largura da lista */ |  | ||||||
|     height: 20%; /* Aumentando altura para caber o texto dos botões */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Botões individuais - garantindo espaço para o texto */ |  | ||||||
| .DiaryListScreen-NewDiaryButton, |  | ||||||
| .DiaryListScreen-EditDiaryButton, |  | ||||||
| .DiaryListScreen-OpenDiaryButton { |  | ||||||
|     margin: 0 1 1 0; /* Espaço entre os botões */ |  | ||||||
|     height: 1fr; |  | ||||||
|     width: 1fr; |  | ||||||
|     border: round grey; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* As dicas - usando a classe correta */ |  | ||||||
| .DiaryListScreen-DiaryListTips { |  | ||||||
|     width: 100%; /* Largura total quando usando dock */ |  | ||||||
|     height: auto; |  | ||||||
|     text-style: italic; |  | ||||||
|     text-align: center; /* Centraliza o texto dentro do elemento */ |  | ||||||
|     color: $text-muted; |  | ||||||
|     dock: bottom; /* Gruda no fundo da tela */ |  | ||||||
|     margin: 0 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Estilos genéricos que não mudaram */ |  | ||||||
| .option-list--option-highlighted { |  | ||||||
|     background: $primary-darken-2; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .option-list--option-selected { |  | ||||||
|     text-style: bold; |  | ||||||
|     background: $primary; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Header { |  | ||||||
|     background: $primary; |  | ||||||
|     color: $text; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Footer { |  | ||||||
|     background: $primary; |  | ||||||
|     color: $text; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| AboutScreen { |  | ||||||
|     align: center middle; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .AboutScreen_AboutContainer { |  | ||||||
|     align: center middle; |  | ||||||
|     width: 85%; |  | ||||||
|     height: 95%; |  | ||||||
|     border: thick $primary; |  | ||||||
|     background: $surface; |  | ||||||
|     margin: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .AboutScreen_AboutContainer TextArea { |  | ||||||
|     align: center middle; |  | ||||||
|     width: 100%; |  | ||||||
|     height: 55%; |  | ||||||
|     margin: 2; |  | ||||||
|     padding: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .AboutScreen_SubContainer { |  | ||||||
|     align: center middle; |  | ||||||
|     height: 45%; |  | ||||||
|     padding: 1 1; |  | ||||||
|     margin: 1 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .AboutScreen_AboutTitle { |  | ||||||
|     color: $accent; |  | ||||||
|     text-style: bold; |  | ||||||
|     text-align: center; |  | ||||||
|     margin-bottom: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .AboutScreen_AboutVersion { |  | ||||||
|     color: $warning; |  | ||||||
|     text-style: italic; |  | ||||||
|     text-align: center; |  | ||||||
|     margin-bottom: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .AboutScreen_AboutContent { |  | ||||||
|     text-align: center; |  | ||||||
|     margin-bottom: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .AboutScreen_AboutContact, |  | ||||||
| .AboutScreen_AboutAuthor { |  | ||||||
|     color: $text-muted; |  | ||||||
|     text-align: center; |  | ||||||
|     margin-bottom: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .AboutScreen_AboutLicense { |  | ||||||
|     height: 60%; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Screen.-modal { |  | ||||||
|     background: rgba(0, 0, 0, 0.7); /* Escurece o fundo da tela por baixo */ |  | ||||||
|     align: center middle; /* Centraliza o conteúdo (sua modal) que está nesta tela modal */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .NewDiaryModal-Dialog { |  | ||||||
|     width: 60%; /* Largura do diálogo */ |  | ||||||
|     height: auto; /* Altura automática */ |  | ||||||
|     background: $surface; /* Fundo do diálogo */ |  | ||||||
|     border: thick $accent; /* Borda chamativa */ |  | ||||||
|     padding: 2 4; /* Espaçamento interno */ |  | ||||||
|     align: center middle; /* Centraliza conteúdo dentro do diálogo */ |  | ||||||
|     layout: vertical; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .NewDiaryModal-Dialog .NewDiaryModal-Title{ |  | ||||||
|     text-align: center; |  | ||||||
|     text-style: bold; |  | ||||||
|     color: $primary; |  | ||||||
|     margin-bottom: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .NewDiaryModal-NameInput{ |  | ||||||
|     width: 1fr; /* Ocupa a largura disponível */ |  | ||||||
|     margin-bottom: 2; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .NewDiaryModal-ButtonsContainer{ |  | ||||||
|     width: 1fr; |  | ||||||
|     height: auto; |  | ||||||
|     align: center middle; |  | ||||||
|     padding-top: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .NewDiaryModal-ButtonsContainer Button{ |  | ||||||
|     margin: 0 1; |  | ||||||
|     width: 1fr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* EditEntryScreen Styles */ |  | ||||||
| .EditEntryScreen-sub-header { | .EditEntryScreen-sub-header { | ||||||
|     layout: horizontal; |     layout: horizontal; | ||||||
|     background: $primary-darken-1; |     background: $primary-darken-1; | ||||||
|  | @ -234,7 +66,294 @@ Screen.-modal { | ||||||
|     border: none; |     border: none; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* RenameEntryModal Styles */ | AboutScreen { | ||||||
|  |     align: center middle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #AboutScreen_AboutContainer { | ||||||
|  |     align: center middle; | ||||||
|  |     width: 85%; | ||||||
|  |     height: 95%; | ||||||
|  |     border: thick $primary; | ||||||
|  |     background: $surface; | ||||||
|  |     margin: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #AboutScreen_AboutContainer TextArea { | ||||||
|  |     align: center middle; | ||||||
|  |     width: 100%; | ||||||
|  |     height: 55%; | ||||||
|  |     margin: 2; | ||||||
|  |     padding: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #AboutScreen_SubContainer { | ||||||
|  |     align: center middle; | ||||||
|  |     height: 45%; | ||||||
|  |     padding: 1 1; | ||||||
|  |     margin: 1 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #AboutScreen_AboutTitle { | ||||||
|  |     color: $accent; | ||||||
|  |     text-style: bold; | ||||||
|  |     text-align: center; | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #AboutScreen_AboutVersion { | ||||||
|  |     color: $warning; | ||||||
|  |     text-style: italic; | ||||||
|  |     text-align: center; | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #AboutScreen_AboutContent { | ||||||
|  |     text-align: center; | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #AboutScreen_AboutContact, | ||||||
|  | #AboutScreen_AboutAuthor { | ||||||
|  |     color: $text-muted; | ||||||
|  |     text-align: center; | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #AboutScreen_AboutLicense { | ||||||
|  |     height: 60%; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Main container - distributing vertical space */ | ||||||
|  | .DiaryListScreen-DiaryListContainer { | ||||||
|  |     height: 1fr; | ||||||
|  |     width: 100%; | ||||||
|  |     layout: vertical; | ||||||
|  |     align: center top; /* Aligns at the top to follow the wireframe */ | ||||||
|  |     padding: 2 4; /* More space on the sides */ | ||||||
|  |     background: $surface; /* Removing aquamarine to keep it cleaner */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Diary list - main area as in the wireframe */ | ||||||
|  | .DiaryListScreen-DiaryListOptions { | ||||||
|  |     border: round $primary-lighten-2; | ||||||
|  |     background: $surface; | ||||||
|  |     width: 75%; /* Generous width as in the wireframe */ | ||||||
|  |     height: 60%; /* Occupies available space */ | ||||||
|  |     margin: 2 0; /* Vertical margin to separate from other elements */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .DiaryListScreen-DiaryListOptions:focus { | ||||||
|  |     border: round $primary; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Button container - right below the list */ | ||||||
|  | .DiaryListScreen-ButtonsGrid { | ||||||
|  |     layout: horizontal; | ||||||
|  |     align: center middle; | ||||||
|  |     width: 75%; /* Same width as the diary list */ | ||||||
|  |     height: 20%; /* Increasing height to fit button text */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Individual buttons - ensuring space for text */ | ||||||
|  | .DiaryListScreen-NewDiaryButton, | ||||||
|  | .DiaryListScreen-EditDiaryButton, | ||||||
|  | .DiaryListScreen-OpenDiaryButton { | ||||||
|  |     margin: 0 1 1 0; /* Space between buttons */ | ||||||
|  |     height: 1fr; | ||||||
|  |     width: 1fr; | ||||||
|  |     border: round grey; | ||||||
|  |     text-align: center; | ||||||
|  |     content-align: center middle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Tips - using the correct class */ | ||||||
|  | .DiaryListScreen-DiaryListTips { | ||||||
|  |     width: 100%; /* Full width when using dock */ | ||||||
|  |     height: auto; | ||||||
|  |     text-style: italic; | ||||||
|  |     text-align: center; /* Centers text within the element */ | ||||||
|  |     color: $text-muted; | ||||||
|  |     dock: bottom; /* Sticks to the bottom of the screen */ | ||||||
|  |     margin: 0 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Generic styles that haven't changed */ | ||||||
|  | .option-list--option-highlighted { | ||||||
|  |     background: $primary-darken-2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .option-list--option-selected { | ||||||
|  |     text-style: bold; | ||||||
|  |     background: $primary; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Header { | ||||||
|  |     background: $primary; | ||||||
|  |     color: $text; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Footer { | ||||||
|  |     background: $primary; | ||||||
|  |     color: $text; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Screen.-modal { | ||||||
|  |     background: rgba(0, 0, 0, 0.7); /* Darkens the background screen underneath */ | ||||||
|  |     align: center middle; /* Centers the content (your modal) that is in this modal screen */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Style for the new diary modal dialog */ | ||||||
|  | .NewDiaryModal-dialog { | ||||||
|  |     layout: vertical; | ||||||
|  |     width: 60%; | ||||||
|  |     height: auto; | ||||||
|  |     background: $surface; | ||||||
|  |     border: thick $accent; | ||||||
|  |     padding: 2 4; | ||||||
|  |     align: center middle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-title { | ||||||
|  |     text-align: center; | ||||||
|  |     text-style: bold; | ||||||
|  |     color: $primary; | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-label { | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-name-input { | ||||||
|  |     width: 1fr; | ||||||
|  |     margin-bottom: 2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-buttons { | ||||||
|  |     width: 1fr; | ||||||
|  |     height: auto; | ||||||
|  |     align: center middle; | ||||||
|  |     padding-top: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-buttons Button { | ||||||
|  |     margin: 0 1; | ||||||
|  |     width: 1fr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Additional classes for NewDiaryModal */ | ||||||
|  | .NewDiaryModal-Dialog { | ||||||
|  |     layout: vertical; | ||||||
|  |     width: 60%; | ||||||
|  |     height: auto; | ||||||
|  |     background: $surface; | ||||||
|  |     border: thick $accent; | ||||||
|  |     padding: 2 4; | ||||||
|  |     align: center middle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-Title { | ||||||
|  |     text-align: center; | ||||||
|  |     text-style: bold; | ||||||
|  |     color: $primary; | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-NameInput { | ||||||
|  |     width: 1fr; | ||||||
|  |     margin-bottom: 2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-ButtonsContainer { | ||||||
|  |     width: 1fr; | ||||||
|  |     height: auto; | ||||||
|  |     align: center middle; | ||||||
|  |     padding-top: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .NewDiaryModal-CreateDiaryButton, | ||||||
|  | .NewDiaryModal-CancelButton { | ||||||
|  |     margin: 0 1; | ||||||
|  |     width: 1fr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Style for the edit diary modal dialog */ | ||||||
|  | .EditDiaryModal-dialog { | ||||||
|  |     layout: vertical; | ||||||
|  |     width: 60%; | ||||||
|  |     height: auto; | ||||||
|  |     background: $surface; | ||||||
|  |     border: thick $warning; | ||||||
|  |     padding: 2 4; | ||||||
|  |     align: center middle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-title { | ||||||
|  |     text-align: center; | ||||||
|  |     text-style: bold; | ||||||
|  |     color: $warning; | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-label { | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-name-input { | ||||||
|  |     width: 1fr; | ||||||
|  |     margin-bottom: 2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-buttons { | ||||||
|  |     width: 1fr; | ||||||
|  |     height: auto; | ||||||
|  |     align: center middle; | ||||||
|  |     padding-top: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-buttons Button { | ||||||
|  |     margin: 0 1; | ||||||
|  |     width: 1fr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Additional classes for EditDiaryModal */ | ||||||
|  | .EditDiaryModal-Dialog { | ||||||
|  |     layout: vertical; | ||||||
|  |     width: 60%; | ||||||
|  |     height: auto; | ||||||
|  |     background: $surface; | ||||||
|  |     border: thick $warning; | ||||||
|  |     padding: 2 4; | ||||||
|  |     align: center middle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-Title { | ||||||
|  |     text-align: center; | ||||||
|  |     text-style: bold; | ||||||
|  |     color: $warning; | ||||||
|  |     margin-bottom: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-NameInput { | ||||||
|  |     width: 1fr; | ||||||
|  |     margin-bottom: 2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-ButtonsContainer { | ||||||
|  |     width: 1fr; | ||||||
|  |     height: auto; | ||||||
|  |     align: center middle; | ||||||
|  |     padding-top: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .EditDiaryModal-SaveButton, | ||||||
|  | .EditDiaryModal-CancelButton { | ||||||
|  |     margin: 0 1; | ||||||
|  |     width: 1fr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Style for the rename entry modal dialog */ | ||||||
| .RenameEntryModal-dialog { | .RenameEntryModal-dialog { | ||||||
|     layout: vertical; |     layout: vertical; | ||||||
|     width: 60%; |     width: 60%; | ||||||
|  | @ -252,10 +371,6 @@ Screen.-modal { | ||||||
|     margin-bottom: 1; |     margin-bottom: 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .RenameEntryModal-label { |  | ||||||
|     margin-bottom: 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .RenameEntryModal-name-input { | .RenameEntryModal-name-input { | ||||||
|     width: 1fr; |     width: 1fr; | ||||||
|     margin-bottom: 2; |     margin-bottom: 2; | ||||||
|  | @ -268,7 +383,8 @@ Screen.-modal { | ||||||
|     padding-top: 1; |     padding-top: 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .RenameEntryModal-buttons Button { | .RenameEntryModal-save-button, | ||||||
|  | .RenameEntryModal-cancel-button { | ||||||
|     margin: 0 1; |     margin: 0 1; | ||||||
|     width: 1fr; |     width: 1fr; | ||||||
| } | }  | ||||||
|  | @ -22,7 +22,7 @@ class UIApp(App): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def on_mount(self) -> None: |     def on_mount(self) -> None: | ||||||
|         """Chamado quando a app inicia. Carrega a tela principal.""" |         """Called when the app starts. Loads the main screen.""" | ||||||
|         self.push_screen(DiaryListScreen()) |         self.push_screen(DiaryListScreen()) | ||||||
| 
 | 
 | ||||||
|     def get_system_commands(self, screen: Screen) -> Iterable[SystemCommand]: |     def get_system_commands(self, screen: Screen) -> Iterable[SystemCommand]: | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue