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,12 +92,28 @@ 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"""
|
||||||
try:
|
try:
|
||||||
|
|
@ -125,6 +139,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"""
|
||||||
if self.is_refreshing:
|
if self.is_refreshing:
|
||||||
|
|
@ -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