diff --git a/app.py b/app.py index 25a298d..833d84a 100644 --- a/app.py +++ b/app.py @@ -575,35 +575,62 @@ def api_content_timestamp(): return jsonify({'error': 'Failed to get content timestamp'}), 500 +def build_comment_tree(comments): + """Build a hierarchical comment tree from flat comment list""" + # Create lookup dict by UUID + comment_dict = {c['uuid']: {**c, 'replies': []} for c in comments} + + # Build tree structure + root_comments = [] + for comment in comments: + parent_uuid = comment.get('parent_comment_uuid') + if parent_uuid and parent_uuid in comment_dict: + # Add as reply to parent + comment_dict[parent_uuid]['replies'].append(comment_dict[comment['uuid']]) + else: + # Top-level comment + root_comments.append(comment_dict[comment['uuid']]) + + # Sort at each level by timestamp + def sort_tree(comments_list): + comments_list.sort(key=lambda x: x.get('timestamp', 0)) + for comment in comments_list: + if comment.get('replies'): + sort_tree(comment['replies']) + + sort_tree(root_comments) + return root_comments + + @app.route('/post/') def post_detail(post_id): """Serve individual post detail page with modern theme""" try: # Load platform configuration platform_config = load_platform_config() - + # Use cached data for better performance cached_posts, cached_comments = _load_posts_cache() - + # Get post data from cache post_data = cached_posts.get(post_id) if not post_data: return render_template('404.html'), 404 - + # Add source display name post_data['source_display'] = get_display_name_for_source( post_data.get('platform', ''), post_data.get('source', ''), platform_config ) - - # Get comments from cache - comments = cached_comments.get(post_id, []) - logger.info(f"Loading post {post_id}: found {len(comments)} comments") - # Sort comments by timestamp - comments.sort(key=lambda x: x.get('timestamp', 0)) - + # Get comments from cache + comments_flat = cached_comments.get(post_id, []) + logger.info(f"Loading post {post_id}: found {len(comments_flat)} comments") + + # Build comment tree + comments = build_comment_tree(comments_flat) + # Load user settings if authenticated user_settings = {} if current_user.is_authenticated: @@ -611,9 +638,9 @@ def post_detail(post_id): user_settings = json.loads(current_user.settings) if current_user.settings else {} except: user_settings = {} - + return render_template('post_detail.html', post=post_data, comments=comments, user_settings=user_settings) - + except Exception as e: print(f"Error loading post {post_id}: {e}") return render_template('404.html'), 404 diff --git a/templates/post_detail.html b/templates/post_detail.html index c83bb02..0b8e714 100644 --- a/templates/post_detail.html +++ b/templates/post_detail.html @@ -135,25 +135,37 @@

Comments ({{ comments|length }})

- + + {% macro render_comment(comment, depth=0) %} +
+
+ {{ comment.author }} + + {{ moment(comment.timestamp).fromNow() if moment else 'Recently' }} +
+
+ {{ comment.content | safe | nl2br }} +
+ + + {% if comment.replies %} +
+ {% for reply in comment.replies %} + {{ render_comment(reply, depth + 1) }} + {% endfor %} +
+ {% endif %} +
+ {% endmacro %} + {% if comments %}
{% for comment in comments %} -
-
- {{ comment.author }} - - {{ moment(comment.timestamp).fromNow() if moment else 'Recently' }} -
-
- {{ comment.content | safe | nl2br }} -
- -
+ {{ render_comment(comment) }} {% endfor %}
{% else %} @@ -554,12 +566,24 @@ .comment { padding: 20px 0; border-bottom: 1px solid #f1f5f9; + position: relative; } .comment:last-child { border-bottom: none; } +/* Threaded comment styling */ +.comment[style*="margin-left"] { + padding-left: 16px; + border-left: 2px solid #e2e8f0; + border-bottom: none; +} + +.comment-replies { + margin-top: 8px; +} + .comment-header { display: flex; align-items: center;