1
0
mirror of https://github.com/algora-io/tv.git synced 2024-11-26 01:00:20 +02:00

revamp chat

This commit is contained in:
zafer 2024-06-23 18:02:01 +03:00
parent ece3051b50
commit cfe3f03bf4
5 changed files with 128 additions and 26 deletions

View File

@ -34,6 +34,8 @@ defmodule Algora.Chat do
select_merge: %{
platform: e.platform,
sender_handle: coalesce(u.handle, e.handle),
sender_name: coalesce(coalesce(u.name, e.name), e.handle),
sender_avatar_url: coalesce(u.avatar_url, e.avatar_url),
channel_id: c.id
},
where: m.video_id == ^video.id
@ -63,6 +65,8 @@ defmodule Algora.Chat do
select_merge: %{
platform: e.platform,
sender_handle: coalesce(u.handle, e.handle),
sender_name: coalesce(coalesce(u.name, e.name), e.handle),
sender_avatar_url: coalesce(u.avatar_url, e.avatar_url),
channel_id: c.id
},
where: m.id == ^id

View File

@ -8,6 +8,8 @@ defmodule Algora.Chat.Message do
field :body, :string
field :platform, :string, virtual: true
field :sender_handle, :string, virtual: true
field :sender_name, :string, virtual: true
field :sender_avatar_url, :string, virtual: true
field :channel_id, :integer, virtual: true
belongs_to :entity, Entity
belongs_to :user, User

View File

@ -0,0 +1,71 @@
defmodule AlgoraWeb.Components.Avatar do
@moduledoc false
use Phoenix.Component
attr(:src, :string)
attr(:alt, :string)
attr(:class, :string, default: nil)
attr(:rest, :global)
def user_avatar(assigns) do
~H"""
<.avatar class={@class} {@rest}>
<.avatar_fallback class="fallback">
<%= @alt
|> String.first()
|> String.upcase() %>
</.avatar_fallback>
<.avatar_image src={@src} alt={@alt} />
</.avatar>
"""
end
attr(:class, :string, default: nil)
attr(:rest, :global)
slot(:inner_block, required: true)
def avatar(assigns) do
~H"""
<span class={cn(["flex relative overflow-hidden", @class])} {@rest}>
<%= render_slot(@inner_block) %>
</span>
"""
end
attr(:src, :string)
attr(:alt, :string)
attr(:class, :string, default: nil)
attr(:rest, :global)
def avatar_image(assigns) do
~H"""
<img
class={cn(["aspect-square h-full w-full absolute", @class])}
src={@src}
alt={@alt}
{@rest}
phx-update="ignore"
style="display:none"
onload="this.style.display=''"
/>
"""
end
attr(:class, :string, default: nil)
attr(:rest, :global)
slot(:inner_block, required: false)
def avatar_fallback(assigns) do
~H"""
<span
class={cn(["absolute flex h-full w-full items-center justify-center rounded-full", @class])}
{@rest}
>
<%= render_slot(@inner_block) %>
</span>
"""
end
# TODO
defp cn(x), do: x
end

View File

@ -2,6 +2,8 @@ defmodule AlgoraWeb.ChatLive do
use AlgoraWeb, :live_view
require Logger
import AlgoraWeb.Components.Avatar
alias Algora.{Accounts, Library, Chat}
alias AlgoraWeb.{LayoutComponent, RTMPDestinationIconComponent}
@ -67,20 +69,33 @@ defmodule AlgoraWeb.ChatLive do
id="chat-messages"
phx-hook="Chat"
phx-update="stream"
class="text-sm break-words flex-1 scrollbar-thin overflow-y-auto inset-0 h-[400px] py-4"
class="text-sm break-words flex-1 scrollbar-thin overflow-y-auto inset-0 h-[400px] py-4 space-y-2.5"
>
<div :for={{id, message} <- @streams.messages} id={id} class="px-4">
<RTMPDestinationIconComponent.icon
:if={message.platform != "algora"}
class="inline-flex w-5 h-5 shrink-0 mr-0.5"
icon={String.to_atom(message.platform)}
/>
<span class={"font-semibold #{if(system_message?(message), do: "text-emerald-400", else: "text-indigo-400")}"}>
<%= message.sender_handle %>:
</span>
<span class="font-medium text-gray-100">
<%= message.body %>
</span>
<div
:for={{id, message} <- @streams.messages}
id={id}
class="px-4 flex items-start gap-2"
>
<div class="relative h-6 w-6 shrink-0">
<.user_avatar
src={message.sender_avatar_url}
alt={message.sender_handle}
class="rounded-full h-6 w-6 [&_.fallback]:bg-gray-700 [&_.fallback]:text-xs"
/>
<RTMPDestinationIconComponent.icon
:if={message.platform != "algora"}
class="absolute -right-1 -bottom-1 flex w-4 h-4 shrink-0 bg-[#110f2c]"
icon={String.to_atom(message.platform)}
/>
</div>
<div>
<span class={"font-semibold #{if(system_message?(message), do: "text-indigo-400", else: "text-emerald-400")}"}>
<%= message.sender_name %>
</span>
<span class="font-medium text-gray-100">
<%= message.body %>
</span>
</div>
</div>
</div>
</div>

View File

@ -2,6 +2,7 @@ defmodule AlgoraWeb.VideoLive do
use AlgoraWeb, :live_view
require Logger
import Ecto.Query, warn: false
import AlgoraWeb.Components.Avatar
alias Algora.{Accounts, Library, Storage, Chat, Repo}
alias Algora.Events.Event
@ -421,7 +422,7 @@ defmodule AlgoraWeb.VideoLive do
phx-hook="Chat"
phx-update="stream"
class={[
"text-sm break-words flex-1 scrollbar-thin overflow-y-auto",
"text-sm break-words flex-1 scrollbar-thin overflow-y-auto space-y-2.5",
if(@channel.solving_challenge,
do: "h-[calc(100svh-56.25vw-415px)] sm:h-[calc(100vh-19.5rem)]",
else: "h-[calc(100svh-56.25vw-375px)] sm:h-[calc(100vh-12rem)]"
@ -431,19 +432,28 @@ defmodule AlgoraWeb.VideoLive do
<div
:for={{id, message} <- @streams.messages}
id={id}
class="group hover:bg-white/5 relative px-4"
class="group hover:bg-white/5 relative px-4 flex items-start gap-2"
>
<RTMPDestinationIconComponent.icon
:if={message.platform != "algora"}
class="inline-flex w-5 h-5 shrink-0 mr-0.5"
icon={String.to_atom(message.platform)}
/>
<span class={"font-semibold #{if(system_message?(message), do: "text-emerald-400", else: "text-indigo-400")}"}>
<%= message.sender_handle %>:
</span>
<span class="font-medium text-gray-100">
<%= message.body %>
</span>
<div class="relative h-6 w-6 shrink-0">
<.user_avatar
src={message.sender_avatar_url}
alt={message.sender_handle}
class="rounded-full h-full w-full [&_.fallback]:bg-gray-700 [&_.fallback]:text-xs"
/>
<RTMPDestinationIconComponent.icon
:if={message.platform != "algora"}
class="absolute -right-1 -bottom-1 flex w-4 h-4 shrink-0 bg-[#110f2c]"
icon={String.to_atom(message.platform)}
/>
</div>
<div>
<span class={"font-semibold #{if(system_message?(message), do: "text-indigo-400", else: "text-emerald-400")}"}>
<%= message.sender_name %>
</span>
<span class="font-medium text-gray-100">
<%= message.body %>
</span>
</div>
<button
:if={@current_user && Chat.can_delete?(@current_user, message)}
phx-click="delete"