Commit 89f9571a authored by Tereza Hrbková's avatar Tereza Hrbková
Browse files

Merge branch 'ui-changes' into 'master'

fix replies

See merge request xtefr/harmonis!15
parents 44275baf f591176f
Loading
Loading
Loading
Loading
+83 −64
Original line number Diff line number Diff line
@@ -15,8 +15,26 @@ class SearchPage extends StatelessWidget {
    final colorScheme = Theme.of(context).colorScheme;

    return PageTemplate(
      body: Column(
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Padding(padding: const EdgeInsets.only(left: 8.0),
            child:
            Text(
              'Search',
              style: Theme.of(context)
                  .textTheme
                  .headlineMedium
                  ?.copyWith(
                color: colorScheme.onSurface,
                fontWeight: FontWeight.bold,
              ),
            ),
            ),
            const SizedBox(height: 16.0),

            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 8.0).copyWith(top: 10.0),
              child: TextField(
@@ -40,12 +58,12 @@ class SearchPage extends StatelessWidget {
            ),
            Expanded(
              child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 8.0).copyWith(bottom: 104.0),
                padding: const EdgeInsets.symmetric(horizontal: 0.0).copyWith(bottom: 104.0),
                child: StreamBuilder<List<SongPostDTO>>(
                  stream: songPostService.getSearchResults(),
                  builder: (context, snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting) {
                    return Center(child: CircularProgressIndicator());
                      return const Center(child: CircularProgressIndicator());
                    }

                    if (snapshot.hasError) {
@@ -89,6 +107,7 @@ class SearchPage extends StatelessWidget {
            ),
          ],
        ),
      ),
    );
  }
}
+86 −33
Original line number Diff line number Diff line
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:harmonis/songPost/post_type.dart';
import 'package:harmonis/songPost/service/song_post_service.dart';
import 'package:harmonis/userInteraction/model/comment_DTO.dart';
import 'package:harmonis/common/comment_input_field.dart';

import '../../user/services/userService.dart';
import '../post_type.dart';

class SongComment extends StatefulWidget {
  final CommentDTO comment;
@@ -15,12 +14,12 @@ class SongComment extends StatefulWidget {
  final VoidCallback onExpand;

  SongComment({
    super.key,
    Key? key,
    required this.comment,
    required this.songPostUid,
    required this.expanded,
    required this.onExpand,
  });
  }) : super(key: key);

  @override
  State<SongComment> createState() => _SongCommentState();
@@ -28,7 +27,8 @@ class SongComment extends StatefulWidget {

class _SongCommentState extends State<SongComment> {
  final TextEditingController replyController = TextEditingController();
  final userService = GetIt.instance<UserService>();
  final SongPostService songPostService = GetIt.instance<SongPostService>();
  final UserService userService = GetIt.instance<UserService>();

  String? authorName;

@@ -51,23 +51,29 @@ class _SongCommentState extends State<SongComment> {
    });
  }

  void _addReply(String commentId, String replyText) {
  Future<void> _addReply(String commentId, String replyText) async {
    if (replyText.trim().isEmpty) return;

    final currentUser = FirebaseAuth.instance.currentUser;
    if (currentUser == null) {
      return;
    }

    final reply = CommentDTO(
      uid: DateTime.now().toString(),
      uid: null,
      text: replyText.trim(),
      authorUId: FirebaseAuth.instance.currentUser!.uid,
      postType: PostType.songPost,
      authorUId: currentUser.uid,
      postType: PostType.comment,
      replies: [],
      timeStamp: DateTime.now(),
    );

    GetIt.instance<SongPostService>().addReply(widget.songPostUid, commentId, reply);

    setState(() {
      widget.comment.replies.add(reply);
    });
    try {
      await songPostService.addReply(widget.songPostUid, commentId, reply);
      replyController.clear();
    } catch (e) {
      print('Failed to add reply: $e');
    }
  }

  @override
@@ -128,32 +134,79 @@ class _SongCommentState extends State<SongComment> {
            ),
            if (widget.expanded) ...[
              const SizedBox(height: 8),
              for (CommentDTO reply in widget.comment.replies)
                Padding(
                  padding: const EdgeInsets.only(bottom: 8.0),
              StreamBuilder<List<CommentDTO>>(
                stream: songPostService.getReplies(widget.songPostUid, widget.comment.uid!),
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return Text(
                      'Error loading replies.',
                      style: TextStyle(color: Colors.red),
                    );
                  }
                  if (!snapshot.hasData) {
                    return Center(child: CircularProgressIndicator());
                  }
                  final replies = snapshot.data!;
                  if (replies.isEmpty) {
                    return Text(
                      'No replies yet',
                      style: TextStyle(color: Colors.grey[600]),
                    );
                  }
                  return Column(
                    children: replies.map((reply) {
                      return Padding(
                        padding: const EdgeInsets.only(bottom: 8.0, left: 4.0, right: 4.0),
                        child: Row(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            const Icon(Icons.reply, size: 16, color: Colors.grey),
                            const SizedBox(width: 8),
                            Expanded(
                        child: Text(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    reply.authorUId,
                                    style: Theme.of(context)
                                        .textTheme
                                        .bodySmall
                                        ?.copyWith(color: Colors.grey[600], fontWeight: FontWeight.normal),
                                  ),
                                  const SizedBox(height: 2),
                                  Text(
                                    reply.text,
                                    style: Theme.of(context)
                                        .textTheme
                                        .bodyLarge
                                        ?.copyWith(color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.normal),
                                  ),
                                  const SizedBox(height: 2),
                                  Text(
                                    '${reply.timeStamp.hour.toString().padLeft(2, '0')}:${reply.timeStamp.minute.toString().padLeft(2, '0')} on ${reply.timeStamp.day}/${reply.timeStamp.month}/${reply.timeStamp.year}',
                                    style: Theme.of(context)
                                        .textTheme
                                        .bodySmall
                                        ?.copyWith(color: Colors.grey[600]),
                                  ),
                                  const SizedBox(height: 8),
                                ],
                              ),
                            ),
                          ],
                        ),
                      );
                    }).toList(),
                  );
                },
              ),
              const SizedBox(height: 8),
              CommentInputField(
                controller: replyController,
                onSend: () {
                  final replyText = replyController.text.trim();
                  if (replyText.isNotEmpty) {
                    _addReply(widget.comment.uid!, replyText);
                    replyController.clear();
                  }
                },
              ),
+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ class AddSongPostPage extends StatelessWidget {

    return PageTemplate(
      body: Padding(
          padding: const EdgeInsets.all(16.0),
          padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
+21 −0
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ class SongPostRepository {
        .collection('songPosts')
        .doc(songPostId)
        .collection('comments')
        .orderBy('timeStamp', descending: true)
        .snapshots()
        .map((snapshot) {
      return snapshot.docs
@@ -203,4 +204,24 @@ class SongPostRepository {
        .collection('replies');
    await repliesRef.add(reply.toJson());
  }

  Stream<List<CommentDTO>> getRepliesForComment(String songPostId, String commentId) {
    return fireStore
        .collection('songPosts')
        .doc(songPostId)
        .collection('comments')
        .doc(commentId)
        .collection('replies')
        .orderBy('timeStamp', descending: false)
        .snapshots()
        .map((snapshot) {
      return snapshot.docs.map((doc) {
        final data = doc.data();
        return CommentDTO.fromJson(data).copyWith(uid: doc.id);
      }).toList();
    }).handleError((error) {
      print('Error fetching replies for comment $commentId: $error');
      return [];
    });
  }
}
+6 −2
Original line number Diff line number Diff line
@@ -88,6 +88,10 @@ class SongPostService {
    }
  }

  Stream<List<CommentDTO>> getReplies(String songPostId, String commentId) {
    return songPostRepository.getRepliesForComment(songPostId, commentId);
  }

  Stream<Comments> getComments(String postUid) {
    return songPostRepository.getCommentsForSongPost(postUid);
  }
@@ -123,8 +127,8 @@ class SongPostService {
    return false;
  }

  void addReply(String postId, String commentId, CommentDTO reply) {
    songPostRepository.addReplyToComment(postId, commentId, reply);
  Future<void> addReply(String postId, String commentId, CommentDTO reply) async {
    await songPostRepository.addReplyToComment(postId, commentId, reply);
  }

  Future<void> deleteSongPost(String postId) async {
Loading