Skip to content

Commit

Permalink
Fix scrolling to bottom when new messages come in not working and for…
Browse files Browse the repository at this point in the history
…ce retry some webhook calls to better mock the fb api
  • Loading branch information
mjarkk committed Jul 1, 2024
1 parent 3915229 commit 5224546
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 78 deletions.
37 changes: 36 additions & 1 deletion go/lib/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,49 @@ func NotivyMessage(message models.Message, awaitResponse bool) error {

if !awaitResponse {
go func() {
err := makeWebhookRequest(payload)
err := makeWebhookRequestWithRandomForcedRetries(payload)
if err != nil {
fmt.Println("failed to call webhook, error response:", err.Error())
}
}()
return nil
}

return makeWebhookRequestWithRandomForcedRetries(payload)
}

func makeWebhookRequestWithRandomForcedRetries(payload []byte) error {
randomSleepDuration := rand.Intn(int(time.Millisecond * 1500))
time.Sleep(time.Duration(randomSleepDuration))

err := makeWebhookRequest(payload)
if err != nil {
return err
}

if rand.Intn(100) > 20 {
return nil
}
// Yolo retry 20% of all request.
// Facebooks api also does this and can be a source of bugs hence why we also do this.

randomSleepDuration = rand.Intn(int(time.Second * 10))
time.Sleep(time.Duration(randomSleepDuration))

err = makeWebhookRequest(payload)
if err != nil {
return err
}

if rand.Intn(100) > 10 {
return nil
}
// Yolo retry 10% of all request (this should be 2% of the time in total).
// Same reason as above

randomSleepDuration = rand.Intn(int(time.Minute))
time.Sleep(time.Duration(randomSleepDuration))

return makeWebhookRequest(payload)
}

Expand Down
77 changes: 77 additions & 0 deletions src/components/conversations/conversation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { ShowMessage } from "./singleMessage"
import { Input } from "@/components/ui/input"
import { post } from "@/services/fetch"
import { FormEvent, useEffect, useRef, useState } from "react"
import { useConversationsStore, type Conversation } from "@/services/state"

export interface ConversationProps {
conversation: Conversation
}

export function Conversation(props: ConversationProps) {
const { updateConversation } = useConversationsStore()
const [msgCount, setMsgCount] = useState(0)
const messagesEndRef = useRef<HTMLDivElement>(null)

const onSendMessage = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()

const target = e.target as HTMLFormElement

const formData = new FormData(target)
const message = Object.fromEntries(formData).message
if (message === "") return

target.reset()
const response = await post(`/api/conversations/${props.conversation.ID}`, {
message,
})
updateConversation(await response.json())
}

useEffect(() => {
if (msgCount === props.conversation.messages.length) {
return
}

const smooth = msgCount > 0
setMsgCount(props.conversation.messages.length)

const parentEl = messagesEndRef.current?.parentElement?.parentElement
if (!parentEl) {
return
}

parentEl.scroll({
top: parentEl.scrollHeight - parentEl.getBoundingClientRect().height,
behavior: smooth ? "smooth" : "instant",
})
}, [props])

return (
<div key={props.conversation.phoneNumber} bg-zinc-900 w-100 rounded>
<h4
m-0
p-3
border-solid
border-0
border-b-2
border-zinc-700
text-zinc-200
>
{props.conversation.phoneNumber}
</h4>
<div h-130 overflow-y-auto>
<div flex flex-col justify-end>
{props.conversation.messages.map((message) => (
<ShowMessage key={message.whatsappID} message={message} />
))}
<div ref={messagesEndRef} />
</div>
</div>
<form bg-zinc-700 onSubmit={onSendMessage}>
<Input type="text" name="message" placeholder="message" />
</form>
</div>
)
}
77 changes: 4 additions & 73 deletions src/components/conversations/conversations.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { fetch, post } from "@/services/fetch"
import { FormEvent, useEffect, useRef, useState } from "react"
import { fetch } from "@/services/fetch"
import { useEffect, useState } from "react"
import { OpenCloseButton } from "../openCloseButton"
import { useConversationsStore, type Conversation } from "@/services/state"
import { useConversationsStore } from "@/services/state"
import { NewChatDialog } from "./new"
import { ShowMessage } from "./singleMessage"
import { Conversation } from "./conversation"

export function Conversations() {
const [open, setOpen] = useState(true)
Expand Down Expand Up @@ -50,71 +49,3 @@ export function Conversations() {
</>
)
}

interface ConversationProps {
conversation: Conversation
}

function Conversation({ conversation }: ConversationProps) {
const { updateConversation } = useConversationsStore()
const [msgCount, setMsgCount] = useState(0)
const messagesEndRef = useRef<HTMLDivElement>(null)

const onSendMessage = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()

const target = e.target as HTMLFormElement

const formData = new FormData(target)
const message = Object.fromEntries(formData).message
if (message === "") return

target.reset()
const response = await post(`/api/conversations/${conversation.ID}`, {
message,
})
updateConversation(await response.json())
}

useEffect(() => {
if (msgCount === conversation.messages.length) {
return
}

const smooth = msgCount > 0
setMsgCount(conversation.messages.length)

if (messagesEndRef.current) {
messagesEndRef.current.scrollIntoView({
behavior: smooth ? "smooth" : "instant",
})
}
}, [msgCount, conversation])

return (
<div key={conversation.phoneNumber} bg-zinc-900 w-100 rounded>
<h4
m-0
p-3
border-solid
border-0
border-b-2
border-zinc-700
text-zinc-200
>
{conversation.phoneNumber}
</h4>
<div h-130 overflow-y-auto>
<div flex flex-col justify-end>
{conversation.messages.map((message) => (
<ShowMessage key={message.whatsappID} message={message} />
))}
<div ref={messagesEndRef} />
</div>
</div>
<form bg-zinc-700 onSubmit={onSendMessage}>
<Input type="text" name="message" placeholder="message" />
</form>
</div>
)
}
4 changes: 0 additions & 4 deletions src/components/conversations/singleMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,6 @@ function Formatted({ text }: { text: string }) {
lastPart.text = "*" + lastPart.text
}

if (parts.length > 1) {
console.log(parts)
}

return parts.map((el, idx) => (
<span
key={idx}
Expand Down

0 comments on commit 5224546

Please sign in to comment.