Implement seamless auto-loading timeline navigation
- Remove explicit "Load more posts" items from timeline view - Auto-load more posts when down arrow pressed at timeline end - Create seamless infinite-scroll experience for better UX - Maintain focus on newly loaded content for smooth navigation - Reduce status message display time to 1 second for less interruption - Update accessibility name to "Timeline Tree" for consistency This creates a more natural browsing experience where users can continuously navigate through their timeline without manual loading prompts. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -116,7 +116,7 @@ class TimelineView(QTreeWidget):
|
|||||||
self.setFocusPolicy(Qt.StrongFocus)
|
self.setFocusPolicy(Qt.StrongFocus)
|
||||||
|
|
||||||
# Set accessible properties
|
# Set accessible properties
|
||||||
self.setAccessibleName("Timeline")
|
self.setAccessibleName("Timeline Tree")
|
||||||
self.setAccessibleDescription("Timeline showing posts and conversations")
|
self.setAccessibleDescription("Timeline showing posts and conversations")
|
||||||
|
|
||||||
def set_timeline_type(self, timeline_type: str):
|
def set_timeline_type(self, timeline_type: str):
|
||||||
@ -1151,13 +1151,10 @@ class TimelineView(QTreeWidget):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def add_load_more_item(self):
|
def add_load_more_item(self):
|
||||||
"""Add a 'Load more posts' item at the bottom of the timeline"""
|
"""Legacy method - no longer adds visible 'Load more posts' item"""
|
||||||
load_more_item = QTreeWidgetItem(["Load more posts (Press Enter)"])
|
# Auto-loading on down arrow makes explicit load more items unnecessary
|
||||||
load_more_item.setData(0, Qt.UserRole, "load_more") # Special marker
|
# Keep method for compatibility but don't add any visible items
|
||||||
load_more_item.setData(
|
pass
|
||||||
0, Qt.AccessibleTextRole, "Load more posts from timeline"
|
|
||||||
)
|
|
||||||
self.addTopLevelItem(load_more_item)
|
|
||||||
|
|
||||||
def load_more_posts(self):
|
def load_more_posts(self):
|
||||||
"""Load more posts from the current timeline"""
|
"""Load more posts from the current timeline"""
|
||||||
@ -1200,11 +1197,8 @@ class TimelineView(QTreeWidget):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if more_data:
|
if more_data:
|
||||||
# Remember current "Load more" item position
|
# Get current position to add new posts
|
||||||
load_more_index = self.get_load_more_item_index()
|
insert_index = self.topLevelItemCount()
|
||||||
|
|
||||||
# Remove current "Load more" item
|
|
||||||
self.remove_load_more_item()
|
|
||||||
|
|
||||||
# Add new posts to existing list
|
# Add new posts to existing list
|
||||||
self.load_additional_timeline_data(more_data)
|
self.load_additional_timeline_data(more_data)
|
||||||
@ -1213,24 +1207,18 @@ class TimelineView(QTreeWidget):
|
|||||||
self.oldest_post_id = more_data[-1]["id"]
|
self.oldest_post_id = more_data[-1]["id"]
|
||||||
|
|
||||||
# Add new posts to the tree without rebuilding everything
|
# Add new posts to the tree without rebuilding everything
|
||||||
self.add_new_posts_to_tree(more_data, load_more_index)
|
self.add_new_posts_to_tree(more_data, insert_index)
|
||||||
|
|
||||||
# Add new "Load more" item at the end
|
# Focus on the first newly added post so user can continue reading
|
||||||
self.add_load_more_item()
|
if insert_index < self.topLevelItemCount():
|
||||||
|
first_new_item = self.topLevelItem(insert_index)
|
||||||
# Focus on the first newly added post so user can arrow down to read them
|
|
||||||
if (
|
|
||||||
load_more_index is not None
|
|
||||||
and load_more_index < self.topLevelItemCount()
|
|
||||||
):
|
|
||||||
first_new_item = self.topLevelItem(load_more_index)
|
|
||||||
if first_new_item:
|
if first_new_item:
|
||||||
self.setCurrentItem(first_new_item)
|
self.setCurrentItem(first_new_item)
|
||||||
self.scrollToItem(first_new_item)
|
self.scrollToItem(first_new_item)
|
||||||
|
|
||||||
if hasattr(self, "parent") and hasattr(self.parent(), "status_bar"):
|
if hasattr(self, "parent") and hasattr(self.parent(), "status_bar"):
|
||||||
self.parent().status_bar.showMessage(
|
self.parent().status_bar.showMessage(
|
||||||
f"Loaded {len(more_data)} more posts", 2000
|
f"Loaded {len(more_data)} more posts", 1000
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if hasattr(self, "parent") and hasattr(self.parent(), "status_bar"):
|
if hasattr(self, "parent") and hasattr(self.parent(), "status_bar"):
|
||||||
@ -1244,20 +1232,12 @@ class TimelineView(QTreeWidget):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_load_more_item_index(self):
|
def get_load_more_item_index(self):
|
||||||
"""Get the index of the 'Load more posts' item"""
|
"""Legacy method - no longer needed as there are no load more items"""
|
||||||
for i in range(self.topLevelItemCount()):
|
|
||||||
item = self.topLevelItem(i)
|
|
||||||
if item.data(0, Qt.UserRole) == "load_more":
|
|
||||||
return i
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def remove_load_more_item(self):
|
def remove_load_more_item(self):
|
||||||
"""Remove the 'Load more posts' item"""
|
"""Legacy method - no longer needed as there are no load more items"""
|
||||||
for i in range(self.topLevelItemCount()):
|
pass
|
||||||
item = self.topLevelItem(i)
|
|
||||||
if item.data(0, Qt.UserRole) == "load_more":
|
|
||||||
self.takeTopLevelItem(i)
|
|
||||||
break
|
|
||||||
|
|
||||||
def load_additional_timeline_data(self, timeline_data):
|
def load_additional_timeline_data(self, timeline_data):
|
||||||
"""Load additional timeline data and append to existing posts"""
|
"""Load additional timeline data and append to existing posts"""
|
||||||
@ -1371,7 +1351,7 @@ class TimelineView(QTreeWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
post = item.data(0, Qt.UserRole)
|
post = item.data(0, Qt.UserRole)
|
||||||
if not post or post == "load_more":
|
if not post:
|
||||||
return
|
return
|
||||||
|
|
||||||
menu = QMenu(self)
|
menu = QMenu(self)
|
||||||
@ -1632,7 +1612,7 @@ class TimelineView(QTreeWidget):
|
|||||||
self.logger.error(f"Error updating conversation display: {e}")
|
self.logger.error(f"Error updating conversation display: {e}")
|
||||||
|
|
||||||
def keyPressEvent(self, event: QKeyEvent):
|
def keyPressEvent(self, event: QKeyEvent):
|
||||||
"""Handle keyboard events, including Enter for poll voting and context menu keys"""
|
"""Handle keyboard events, including Enter for poll voting and automatic loading"""
|
||||||
key = event.key()
|
key = event.key()
|
||||||
current = self.currentItem()
|
current = self.currentItem()
|
||||||
|
|
||||||
@ -1648,15 +1628,22 @@ class TimelineView(QTreeWidget):
|
|||||||
self.customContextMenuRequested.emit(center)
|
self.customContextMenuRequested.emit(center)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Handle Enter key for polls, load more, and post details
|
# Handle down arrow at end of timeline - automatically load more posts
|
||||||
if (key == Qt.Key_Return or key == Qt.Key_Enter) and current:
|
if key == Qt.Key_Down and current:
|
||||||
# Check for special items first
|
# Check if we're at the last post in the timeline
|
||||||
special_data = current.data(0, Qt.UserRole)
|
current_index = self.indexOfTopLevelItem(current)
|
||||||
if special_data == "load_more":
|
total_items = self.topLevelItemCount()
|
||||||
self.load_more_posts()
|
|
||||||
return
|
# If we're at the last post, automatically load more
|
||||||
|
if current_index >= total_items - 1:
|
||||||
|
# Only auto-load if we actually have an API client and more data might be available
|
||||||
|
if self.activitypub_client and self.oldest_post_id:
|
||||||
|
self.load_more_posts()
|
||||||
|
return
|
||||||
|
|
||||||
# Check if current item has poll data
|
# Handle Enter key for post details
|
||||||
|
if (key == Qt.Key_Return or key == Qt.Key_Enter) and current:
|
||||||
|
# Check if current item has post data
|
||||||
try:
|
try:
|
||||||
post_index = self.indexOfTopLevelItem(current)
|
post_index = self.indexOfTopLevelItem(current)
|
||||||
if 0 <= post_index < len(self.posts):
|
if 0 <= post_index < len(self.posts):
|
||||||
|
Reference in New Issue
Block a user