73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
from typing import Optional
|
|
from nicegui import ui
|
|
|
|
|
|
class AutoScrollArea(ui.scroll_area):
|
|
"""A scroll area that automatically scrolls to bottom when new content is added
|
|
|
|
Features:
|
|
- Auto-scrolls to bottom when at bottom and new content arrives
|
|
- Stops auto-scroll when user scrolls up manually
|
|
- Resumes auto-scroll when user scrolls back to bottom
|
|
"""
|
|
|
|
_auto_scroll_enabled: bool = True
|
|
_auto_scroll_timer: Optional[ui.timer] = None
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Set up scroll monitoring
|
|
# self._handle_scroll
|
|
self.on_scroll(self._handle_scroll_event)
|
|
self.on('wheel', self._handle_wheel, ['deltaY'])
|
|
|
|
# Create timer for auto-scrolling
|
|
self._auto_scroll_timer = ui.timer(0.1, lambda: self.scroll_to(percent=1))
|
|
self._auto_scroll_timer.activate()
|
|
|
|
def _scroll_event_test(self, e):
|
|
print(e.vertical_percentage)
|
|
|
|
def _handle_scroll_event(self, event_data):
|
|
"""Handle scroll events to detect when user is at bottom"""
|
|
|
|
if not self._auto_scroll_timer:
|
|
print('no timer instantiated.')
|
|
return
|
|
|
|
# If scrolled to bottom (100%), enable auto-scroll
|
|
if event_data.vertical_percentage > 0.99: # Using 0.99 for some tolerance
|
|
if not self._auto_scroll_timer.active:
|
|
self._auto_scroll_timer.activate()
|
|
|
|
def _handle_wheel(self, event_data):
|
|
"""Handle mouse wheel events to detect manual scrolling"""
|
|
delta_y = event_data.args['deltaY']
|
|
if not self._auto_scroll_timer:
|
|
print('no timer instantiated.')
|
|
return
|
|
# If scrolling up (negative delta), disable auto-scroll
|
|
if delta_y < 0:
|
|
if self._auto_scroll_timer.active:
|
|
self._auto_scroll_timer.deactivate()
|
|
|
|
def enable_auto_scroll(self):
|
|
"""Manually enable auto-scrolling"""
|
|
if self._auto_scroll_timer:
|
|
if not self._auto_scroll_timer.active:
|
|
self._auto_scroll_timer.activate()
|
|
|
|
def disable_auto_scroll(self):
|
|
"""Manually disable auto-scrolling"""
|
|
|
|
if self._auto_scroll_timer:
|
|
if self._auto_scroll_timer.active:
|
|
self._auto_scroll_timer.deactivate()
|
|
|
|
def cleanup(self):
|
|
"""Clean up timer when component is destroyed"""
|
|
if self._auto_scroll_timer:
|
|
self._auto_scroll_timer.deactivate()
|
|
self._auto_scroll_timer = None
|