File size: 3,159 Bytes
a0fda44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { useState } from "react";
import { useDispatch } from "react-redux";
import { chatActions } from "../store/chatSlice";
import useSocket from "../hooks/useSocket";

const useMessageInput = ({ currentChatRoom }) => {
  const { socketEmit } = useSocket();
  const dispatch = useDispatch();
  const [messageEmpty, setMessageEmpty] = useState(true);
  const [caretIndex, setCaretIndex] = useState(0);

  // Get cursor position in input
  function getCaretIndex(event) {
    let position = 0;
    const isSupported = typeof window.getSelection !== "undefined";
    if (isSupported) {
      const selection = window.getSelection();
      if (selection.rangeCount !== 0) {
        const range = window.getSelection().getRangeAt(0);
        const preCaretRange = range.cloneRange();
        preCaretRange.selectNodeContents(event.currentTarget);
        preCaretRange.setEnd(range.endContainer, range.endOffset);
        position = preCaretRange.toString().length;
      }
    }
    setCaretIndex(position);
  }

  // Add emoji to message
  const addEmojiToMessage = ({ getImageUrl }) => {
    dispatch(chatActions.setMode({ mode: "typing" }));
    setMessageEmpty(false);
    const messageInput = document.querySelector("#messageInput");
    const innerHtml = messageInput.innerHTML;
    const emojiString = `<img class="w-[2.5rem] h-[2.5rem] inline-block" src="${getImageUrl()}" />`;

    if (!caretIndex) {
      messageInput.innerHTML = emojiString + messageInput.innerHTML;
      return;
    }

    // Caret index === element index in textContent

    let textContentIndex = 0;
    let innerHtmlIndex = 0;

    let countingNormalText = true;

    for (let char of innerHtml) {
      const htmlRest = innerHtml.slice(innerHtmlIndex);
      // If an image tag is next
      if (htmlRest.startsWith("<img")) {
        countingNormalText = false;
      }

      // If it sees a div
      if (htmlRest.startsWith("<div>")) {
        countingNormalText = false;
      }

      // If it meets ending of div
      if (htmlRest.startsWith("</div>")) {
        countingNormalText = false;
      }

      if (countingNormalText) {
        textContentIndex++;
      }

      if (char === ">" && !countingNormalText) {
        countingNormalText = true;
      }

      innerHtmlIndex++;

      if (textContentIndex === caretIndex) break;
    }

    messageInput.innerHTML =
      innerHtml.slice(0, innerHtmlIndex) +
      emojiString +
      innerHtml.slice(innerHtmlIndex);
  };

  // Handle input to box
  const handleInput = (event) => {
    dispatch(chatActions.setMode({ mode: "typing" }));
    getCaretIndex(event);

    // If message is initially empty change to filled
    if (messageEmpty) {
      setMessageEmpty(false);
    }
    if (!event.currentTarget.innerHTML) {
      dispatch(chatActions.resetMode());
      setMessageEmpty(true);
    }
  };

  // Emit typing event on every key stroke
  const emitTypingEvent = () => {
    socketEmit("user:typing", currentChatRoom._id);
  };

  return {
    addEmojiToMessage,
    handleInput,
    messageEmpty,
    setMessageEmpty,
    getCaretIndex,
    emitTypingEvent,
  };
};

export default useMessageInput;