diff --git a/soul_diary/ui/app/local_storage.py b/soul_diary/ui/app/local_storage.py index 3281d0c..58f3d42 100644 --- a/soul_diary/ui/app/local_storage.py +++ b/soul_diary/ui/app/local_storage.py @@ -16,6 +16,7 @@ class AuthData(BaseModel): class LocalStorage: AUTH_DATA_KEY = "soul_diary.client.auth_data" SHARED_DATA_KEY = "soul_diary.client.shared_data" + CLIENT_DATA_KEY = "soul_diary.client.{key}" def __init__(self, client_storage): self._client_storage = client_storage @@ -65,10 +66,24 @@ class LocalStorage: return tmp_data.get(key) async def clear_shared_data(self): - if not await self.raw_contains(self.SHARED_DATA_KEY): - return + if await self.raw_contains(self.SHARED_DATA_KEY): + await self.raw_remove(self.SHARED_DATA_KEY) - await self.raw_remove(self.SHARED_DATA_KEY) + async def add_client_data(self, key: str, value): + full_key = self.CLIENT_DATA_KEY.format(key=key) + await self.raw_write(key=full_key, value=value) + + async def get_client_data(self, key: str): + full_key = self.CLIENT_DATA_KEY.format(key=key) + + if await self.raw_contains(full_key): + return await self.raw_read(full_key) + + async def remove_client_data(self, key: str): + full_key = self.CLIENT_DATA_KEY.format(key=key) + + if await self.raw_contains(full_key): + await self.raw_remove(full_key) async def raw_contains(self, key: str) -> bool: return await self._client_storage.contains_key_async(key) diff --git a/soul_diary/ui/app/pages/sense.py b/soul_diary/ui/app/pages/sense.py index 1cc06fa..211c0c6 100644 --- a/soul_diary/ui/app/pages/sense.py +++ b/soul_diary/ui/app/pages/sense.py @@ -37,13 +37,13 @@ class SensePage(BasePage): self.body = flet.Text(style=flet.TextThemeStyle.BODY_LARGE) body_container = flet.Container( content=flet.Column(controls=[body_title, self.body]), - margin=flet.margin.symmetric(vertical=30), + margin=flet.margin.symmetric(vertical=15), ) desires_title = flet.Text("Желания", style=flet.TextThemeStyle.HEADLINE_MEDIUM) self.desires = flet.Text(style=flet.TextThemeStyle.BODY_LARGE) desires_container = flet.Container( content=flet.Column(controls=[desires_title, self.desires]), - margin=flet.margin.symmetric(vertical=30), + margin=flet.margin.symmetric(vertical=15), ) return flet.Container( diff --git a/soul_diary/ui/app/pages/sense_list.py b/soul_diary/ui/app/pages/sense_list.py index 32091e9..67db934 100644 --- a/soul_diary/ui/app/pages/sense_list.py +++ b/soul_diary/ui/app/pages/sense_list.py @@ -12,16 +12,27 @@ from .base import BasePage, callback_error_handle class SenseListPage(BasePage): - def __init__(self, view: flet.View, local_storage: LocalStorage): + def __init__(self, view: flet.View, local_storage: LocalStorage, extend: bool = False): self.local_storage = local_storage self.senses = [] self.senses_cards: flet.Column + self.extend = extend super().__init__(view=view) def build(self) -> flet.Container: self.view.vertical_alignment = flet.MainAxisAlignment.START + self.view.scroll = flet.ScrollMode.ALWAYS + view_switch = flet.Switch( + label="Расширенный вид", + value=self.extend, + on_change=self.callback_switch_view, + ) + top_row_left = flet.Row( + controls=[view_switch], + alignment=flet.MainAxisAlignment.START, + ) add_button = flet.IconButton( icon=flet.icons.ADD_CIRCLE_OUTLINE, on_click=self.callback_add_sense, @@ -34,19 +45,21 @@ class SenseListPage(BasePage): icon=flet.icons.LOGOUT, on_click=self.callback_logout, ) - top_container = flet.Container( - content=flet.Row( - controls=[add_button, settings_button, logout_button], - alignment=flet.MainAxisAlignment.END, - ), + top_row_right = flet.Row( + controls=[add_button, settings_button, logout_button], + alignment=flet.MainAxisAlignment.END, + ) + top_row = flet.Row( + controls=[top_row_left, top_row_right], + alignment=flet.MainAxisAlignment.SPACE_BETWEEN, ) self.senses_cards = flet.Column(alignment=flet.alignment.center) return flet.Container( content=flet.Column( - controls=[top_container, self.senses_cards], - width=400, + controls=[top_row, self.senses_cards], + width=600, ), alignment=flet.alignment.center, ) @@ -55,25 +68,38 @@ class SenseListPage(BasePage): await self.render_cards() async def render_cards(self): + function = self.render_extend_card if self.extend else self.render_compact_card backend_client = await get_backend_client(self.local_storage) self.senses = await backend_client.get_sense_list() - self.senses_cards.controls = [ - await self.render_card(sense) - for sense in self.senses - ] + self.senses_cards.controls = [await function(sense) for sense in self.senses] await self.update_async() - async def render_card(self, sense: Sense) -> flet.Card: + async def render_compact_card(self, sense: Sense) -> flet.Card: feelings = flet.Container(content=flet.Text(sense.feelings), expand=True) created_datetime = flet.Text(sense.created_at.strftime("%d %b %H:%M")) + emotions = flet.Row( + controls=[ + flet.Chip( + label=flet.Text(emotion.value), + show_checkmark=False, + selected=True, + ) + for emotion in sense.emotions + ], + wrap=True, + ) + bottom_row = flet.Row( + controls=[created_datetime, emotions], + alignment=flet.MainAxisAlignment.SPACE_BETWEEN, + ) card = flet.Container( content=flet.Card( content=flet.Container( - content=flet.Column(controls=[feelings, created_datetime]), + content=flet.Column(controls=[feelings, bottom_row]), padding=10, ), - width=400, + width=600, height=100, ), on_click=partial(self.callback_card_click, sense_id=sense.id), @@ -85,6 +111,66 @@ class SenseListPage(BasePage): return gesture_detector + async def render_extend_card(self, sense: Sense) -> flet.Card: + title = flet.Text(f"Запись от {sense.created_at.strftime('%d %b %H:%M')}") + + emotions_title = flet.Text("Эмоции", style=flet.TextThemeStyle.HEADLINE_MEDIUM) + emotions = flet.Row( + controls=[ + flet.Chip( + label=flet.Text(emotion.value), + show_checkmark=False, + selected=True, + ) + for emotion in sense.emotions + ], + wrap=True, + ) + + feelings = flet.Text(sense.feelings, style=flet.TextThemeStyle.BODY_LARGE) + feelings_container = flet.Container( + content=flet.Column(controls=[emotions_title, feelings]), + margin=flet.margin.symmetric(vertical=5), + ) + + body_title = flet.Text("Телесные ощущения", style=flet.TextThemeStyle.HEADLINE_MEDIUM) + body = flet.Text(sense.body, style=flet.TextThemeStyle.BODY_LARGE) + body_container = flet.Container( + content=flet.Column(controls=[body_title, body]), + margin=flet.margin.symmetric(vertical=5), + ) + + desires_title = flet.Text("Желания", style=flet.TextThemeStyle.HEADLINE_MEDIUM) + desires = flet.Text(sense.desires, style=flet.TextThemeStyle.BODY_LARGE) + desires_container = flet.Container( + content=flet.Column(controls=[desires_title, desires]), + margin=flet.margin.symmetric(vertical=5), + ) + card = flet.Card( + content=flet.Container( + content=flet.Column(controls=[title, emotions, feelings_container, body_container, + desires_container]), + padding=10, + ), + width=600, + ) + card = flet.Container( + content=card, + on_click=partial(self.callback_card_click, sense_id=sense.id), + ) + gesture_detector = flet.GestureDetector( + mouse_cursor=flet.MouseCursor.CLICK, + content=card, + ) + + return gesture_detector + + @callback_error_handle + async def callback_switch_view(self, event: flet.ControlEvent): + self.extend = event.control.value + await self.local_storage.add_client_data(key="extend_list_view", value=self.extend) + await self.render_cards() + @callback_error_handle async def callback_card_click(self, event: flet.ControlEvent, sense_id: uuid.UUID): await event.page.go_async(SENSE.replace(":sense_id", str(sense_id))) diff --git a/soul_diary/ui/app/views/sense_list.py b/soul_diary/ui/app/views/sense_list.py index 2ce9039..ed236ed 100644 --- a/soul_diary/ui/app/views/sense_list.py +++ b/soul_diary/ui/app/views/sense_list.py @@ -10,4 +10,5 @@ from .base import BaseView class SenseListView(BaseView): async def entrypoint(self, page: flet.Page, params: Params) -> BasePage: local_storage = LocalStorage(client_storage=page.client_storage) - return SenseListPage(view=self.view, local_storage=local_storage) + extend = await local_storage.get_client_data(key="extend_list_view") or False + return SenseListPage(view=self.view, local_storage=local_storage, extend=extend)