Projekt

Obecné

Profil

Stáhnout (5.35 KB) Statistiky
| Větev: | Tag: | Revize:
1
import { VStack, Box, Text, HStack, ScrollView, Flex, Button, CloseIcon, IconButton, TextArea } from "native-base";
2
import { Note } from "../../types/note";
3
import NoteView from "./NoteView";
4
import { MessageIcon } from "../general/Icons";
5
import React, { useCallback, useState } from "react";
6
import { updateNote, deleteNote } from "../../stores/actions/notesThunks";
7
import { ConfirmDialog } from "../general/Dialogs";
8
import { AppDispatch } from "../../stores/store";
9
import { useDispatch } from "react-redux";
10
import { Dimensions } from "react-native";
11

    
12
const NotesListView = (props: { notes: Note[], navigation: any, handleCreateComment: any, requestPending: boolean }) => {
13
    const notes = props.notes;
14

    
15
    const [newComment, setNewComment] = useState<string>("");
16
    const [replyingTo, setReplyingTo] = useState<{ messageId: string; userName: string } | null>(null);
17

    
18
    const [renderedNotes, setRenderedNotes] = useState(6);
19

    
20
    const cancelRef = React.useRef(null);
21

    
22
    const dispatch = useDispatch<AppDispatch>();
23

    
24
    const windowHeight = Dimensions.get('window').height;
25

    
26
    const [confirmDialog, setConfirmDialog] = React.useState<{
27
        headerText?: string;
28
        bodyText?: string;
29
        confirmText?: string;
30
        confirmColor?: string;
31
        cancelRef?: any;
32
        onClose?: () => void;
33
        onSubmit?: () => void;
34
    } | null>(null);
35

    
36
    const handleReply = useCallback((messageId: string, userName: string) => {
37
        setReplyingTo({ messageId, userName });
38
    }, [setReplyingTo]);
39

    
40
    const handleEdit = useCallback((note: Note) => {
41
        if (!props.requestPending) {
42
            dispatch(updateNote(note));
43
        }
44
    }, [dispatch, props.requestPending]);
45

    
46
    const handleDelete = useCallback((messageId: string) => {
47
        if (!props.requestPending) {
48
            dispatch(deleteNote({ noteId: messageId }));
49
        }
50
    }, [dispatch, props.requestPending]);
51

    
52
    const handleScrollEnd = (event : any) => {
53
        const offsetY = event.nativeEvent.contentOffset.y;
54
        const contentHeight = event.nativeEvent.contentSize.height;
55
        const screenHeight = event.nativeEvent.layoutMeasurement.height;
56

    
57
        if (offsetY + screenHeight >= contentHeight - 20) {
58
            // Load more notes when the user is near the end of the list
59
            const nextBatchSize = 5; // Number of notes to render in the next batch
60

    
61
            if((renderedNotes + nextBatchSize) > notes.length && (renderedNotes + nextBatchSize) != notes.length){
62
                setRenderedNotes(notes.length);
63
                // TODO toast display info all rendered
64
            }
65
            else{
66
                setRenderedNotes(renderedNotes + nextBatchSize);
67
                // TODO toast display loading more notes
68
            }
69
        }
70
    };
71

    
72
    console.log(renderedNotes)
73
    console.log(notes.length)
74

    
75
    return (
76
        <VStack>
77
            <Box height={windowHeight - 70 - 160 - (replyingTo ? 40 : 0)} marginBottom={2}>
78
                {/* Notes */}
79
                <ScrollView contentContainerStyle={{ flexGrow: 1 }} onScrollEndDrag={handleScrollEnd}>
80
                    {
81
                        notes && notes.length > 0 ? (
82
                            <VStack>
83
                                {
84
                                    notes.slice(0, renderedNotes).map((note, index) => (
85
                                        <NoteView key={index} note={note} handleReply={handleReply} handleDelete={handleDelete} handleEdit={handleEdit} setConfirmDialog={setConfirmDialog} navigation={props.navigation} />
86
                                    ))
87
                                }
88
                            </VStack>
89
                        ) : (
90
                            <Text>There are no notes.</Text>
91
                        )
92
                    }
93
                </ScrollView>
94
            </Box>
95

    
96
            {/* Create comment */}
97
            {
98
                props.handleCreateComment != null &&
99
                <VStack>
100

    
101
                    {/* Replying to */}
102
                    {replyingTo != null &&
103
                        <Flex direction="row" alignItems="center" justify="flex-end" marginRight={20} height={10}>
104
                            <Text>Replying to {replyingTo.userName}</Text>
105
                            <IconButton onPress={() => setReplyingTo(null)} size="sm" icon={<CloseIcon />} marginLeft="-1%">
106
                            </IconButton>
107
                        </Flex>
108
                    }
109

    
110

    
111
                    {/* Add comment */}
112
                    <HStack height={90} >
113
                        <TextArea
114
                            flex={1}
115
                            placeholder="Add comment"
116
                            fontSize={14}
117
                            value={newComment}
118
                            onChangeText={setNewComment}
119
                            autoCompleteType={undefined}
120
                        />
121
                        <Flex marginLeft={2} marginBottom={8}>
122
                            <Button onPress={() => props.handleCreateComment(newComment, replyingTo)} startIcon={<MessageIcon color="#FFF" />}>
123
                                Send
124
                            </Button>
125
                        </Flex>
126
                    </HStack>
127
                </VStack>
128
            }
129
            <ConfirmDialog {...confirmDialog} isShown={confirmDialog != null} cancelRef={cancelRef} />
130
        </VStack >
131
    );
132
}
133

    
134
export default NotesListView
(2-2/2)