updated chat
This commit is contained in:
parent
b3c07355a8
commit
04ab4523a6
@ -1,7 +1,7 @@
|
||||
PORT=8080
|
||||
DATABASE_URL=postgres://postgres:Timmy0104199%3F@localhost:5432/teg?sslmode=disable
|
||||
JWT_SECRET=tegvideo7010!
|
||||
FRONTEND_ORIGIN=http://10.0.1.25:5173
|
||||
FRONTEND_ORIGIN=http://localhost:5173
|
||||
ADDRESS_SEARCH_PROVIDER=photon
|
||||
ADDRESS_SEARCH_URL=https://photon.komoot.io/api
|
||||
ADDRESS_SEARCH_LANGUAGE=de
|
||||
@ -11,7 +11,7 @@ ADDRESS_SEARCH_USER_AGENT=TEG-App/1.0
|
||||
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_DISPLAY_NAME=Administrator
|
||||
ADMIN_EMAIL=admin@example.com
|
||||
ADMIN_EMAIL=admin@tegdssd.de
|
||||
ADMIN_UNIT=Administration
|
||||
ADMIN_GROUP=admin
|
||||
ADMIN_RIGHTS=admin,users:read,users:write
|
||||
|
||||
@ -352,10 +352,15 @@ func (s *Server) publishChatMessage(
|
||||
}
|
||||
|
||||
for _, recipientID := range recipientIDs {
|
||||
notificationType := "chat.message"
|
||||
if conversationType == "channel" {
|
||||
notificationType = "channel.message"
|
||||
}
|
||||
|
||||
_ = s.createAndPublishNotification(
|
||||
ctx,
|
||||
recipientID,
|
||||
"chat.message",
|
||||
notificationType,
|
||||
title,
|
||||
preview,
|
||||
"chat",
|
||||
|
||||
@ -22,6 +22,7 @@ type notificationPreferencesResponse struct {
|
||||
DeviceJournals bool `json:"deviceJournals"`
|
||||
SystemMessages bool `json:"systemMessages"`
|
||||
ChatMessages bool `json:"chatMessages"`
|
||||
ChannelMessages bool `json:"channelMessages"`
|
||||
DesktopEnabled bool `json:"desktopEnabled"`
|
||||
}
|
||||
|
||||
@ -37,6 +38,7 @@ func defaultNotificationPreferences() notificationPreferencesResponse {
|
||||
DeviceJournals: true,
|
||||
SystemMessages: true,
|
||||
ChatMessages: true,
|
||||
ChannelMessages: true,
|
||||
DesktopEnabled: false,
|
||||
}
|
||||
}
|
||||
@ -108,9 +110,10 @@ func (s *Server) handleUpdateNotificationPreferences(w http.ResponseWriter, r *h
|
||||
device_journals,
|
||||
system_messages,
|
||||
chat_messages,
|
||||
channel_messages,
|
||||
desktop_enabled
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
|
||||
ON CONFLICT (user_id)
|
||||
DO UPDATE SET
|
||||
in_app_enabled = EXCLUDED.in_app_enabled,
|
||||
@ -123,6 +126,7 @@ func (s *Server) handleUpdateNotificationPreferences(w http.ResponseWriter, r *h
|
||||
device_journals = EXCLUDED.device_journals,
|
||||
system_messages = EXCLUDED.system_messages,
|
||||
chat_messages = EXCLUDED.chat_messages,
|
||||
channel_messages = EXCLUDED.channel_messages,
|
||||
desktop_enabled = EXCLUDED.desktop_enabled,
|
||||
updated_at = now()
|
||||
`,
|
||||
@ -137,6 +141,7 @@ func (s *Server) handleUpdateNotificationPreferences(w http.ResponseWriter, r *h
|
||||
input.DeviceJournals,
|
||||
input.SystemMessages,
|
||||
input.ChatMessages,
|
||||
input.ChannelMessages,
|
||||
input.DesktopEnabled,
|
||||
)
|
||||
if err != nil {
|
||||
@ -172,6 +177,7 @@ func (s *Server) getNotificationPreferences(ctx context.Context, userID string)
|
||||
device_journals,
|
||||
system_messages,
|
||||
chat_messages,
|
||||
channel_messages,
|
||||
desktop_enabled
|
||||
FROM notification_preferences
|
||||
WHERE user_id = $1
|
||||
@ -189,6 +195,7 @@ func (s *Server) getNotificationPreferences(ctx context.Context, userID string)
|
||||
&settings.DeviceJournals,
|
||||
&settings.SystemMessages,
|
||||
&settings.ChatMessages,
|
||||
&settings.ChannelMessages,
|
||||
&settings.DesktopEnabled,
|
||||
)
|
||||
|
||||
|
||||
@ -98,6 +98,9 @@ func shouldDeliverNotification(
|
||||
entityType string,
|
||||
) bool {
|
||||
switch {
|
||||
case notificationType == "channel.message":
|
||||
return preferences.ChannelMessages
|
||||
|
||||
case strings.HasPrefix(notificationType, "chat.") || entityType == "chat":
|
||||
return preferences.ChatMessages
|
||||
|
||||
@ -228,7 +231,11 @@ func (s *Server) createAndPublishNotification(
|
||||
notification.Desktop = preferences.DesktopEnabled
|
||||
notification.InApp = preferences.InAppEnabled
|
||||
if notification.EntityType == "chat" {
|
||||
notification.InApp = preferences.ChatMessages
|
||||
if notification.Type == "channel.message" {
|
||||
notification.InApp = preferences.ChannelMessages
|
||||
} else {
|
||||
notification.InApp = preferences.ChatMessages
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -623,6 +623,7 @@ func createSchema(ctx context.Context, db *pgxpool.Pool) error {
|
||||
device_journals BOOLEAN NOT NULL DEFAULT true,
|
||||
system_messages BOOLEAN NOT NULL DEFAULT true,
|
||||
chat_messages BOOLEAN NOT NULL DEFAULT true,
|
||||
channel_messages BOOLEAN NOT NULL DEFAULT true,
|
||||
desktop_enabled BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
@ -631,6 +632,7 @@ func createSchema(ctx context.Context, db *pgxpool.Pool) error {
|
||||
`,
|
||||
|
||||
`ALTER TABLE IF EXISTS notification_preferences ADD COLUMN IF NOT EXISTS chat_messages BOOLEAN NOT NULL DEFAULT true`,
|
||||
`ALTER TABLE IF EXISTS notification_preferences ADD COLUMN IF NOT EXISTS channel_messages BOOLEAN NOT NULL DEFAULT true`,
|
||||
`ALTER TABLE IF EXISTS notification_preferences ADD COLUMN IF NOT EXISTS desktop_enabled BOOLEAN NOT NULL DEFAULT false`,
|
||||
|
||||
`
|
||||
|
||||
@ -24,6 +24,7 @@ import {
|
||||
} from '@heroicons/react/24/outline'
|
||||
import { MapPinIcon as MapPinSolidIcon } from '@heroicons/react/24/solid'
|
||||
import {
|
||||
Fragment,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
@ -291,6 +292,49 @@ function formatTime(value: string) {
|
||||
}).format(new Date(value))
|
||||
}
|
||||
|
||||
function isSameMessageDay(first: string, second: string) {
|
||||
const firstDate = new Date(first)
|
||||
const secondDate = new Date(second)
|
||||
|
||||
if (
|
||||
Number.isNaN(firstDate.getTime()) ||
|
||||
Number.isNaN(secondDate.getTime())
|
||||
) {
|
||||
return first === second
|
||||
}
|
||||
|
||||
return (
|
||||
firstDate.getFullYear() === secondDate.getFullYear() &&
|
||||
firstDate.getMonth() === secondDate.getMonth() &&
|
||||
firstDate.getDate() === secondDate.getDate()
|
||||
)
|
||||
}
|
||||
|
||||
function formatMessageDate(value: string) {
|
||||
const date = new Date(value)
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const today = new Date()
|
||||
const yesterday = new Date(today)
|
||||
yesterday.setDate(today.getDate() - 1)
|
||||
|
||||
if (isSameMessageDay(value, today.toISOString())) {
|
||||
return 'Heute'
|
||||
}
|
||||
if (isSameMessageDay(value, yesterday.toISOString())) {
|
||||
return 'Gestern'
|
||||
}
|
||||
|
||||
return new Intl.DateTimeFormat('de-DE', {
|
||||
weekday: 'long',
|
||||
day: '2-digit',
|
||||
month: 'long',
|
||||
year: date.getFullYear() === today.getFullYear() ? undefined : 'numeric',
|
||||
}).format(date)
|
||||
}
|
||||
|
||||
function formatConversationTime(value?: string | null) {
|
||||
if (!value) {
|
||||
return ''
|
||||
@ -1879,17 +1923,41 @@ export default function ChatPage({ currentUser }: ChatPageProps) {
|
||||
</div>
|
||||
) : (
|
||||
<div className="mx-auto max-w-3xl space-y-4">
|
||||
{messages.map((message) => {
|
||||
{messages.map((message, index) => {
|
||||
const ownMessage = message.sender.id === currentUser.id
|
||||
const previousMessage = messages[index - 1]
|
||||
const showDateSeparator =
|
||||
!previousMessage ||
|
||||
!isSameMessageDay(
|
||||
previousMessage.createdAt,
|
||||
message.createdAt,
|
||||
)
|
||||
const dateLabel = showDateSeparator
|
||||
? formatMessageDate(message.createdAt)
|
||||
: ''
|
||||
|
||||
return (
|
||||
<div
|
||||
key={message.id}
|
||||
className={classNames(
|
||||
ownMessage ? 'justify-end' : 'justify-start',
|
||||
'flex items-end gap-2',
|
||||
<Fragment key={message.id}>
|
||||
{showDateSeparator && (
|
||||
<div
|
||||
role="separator"
|
||||
aria-label={dateLabel}
|
||||
className="flex items-center gap-3 py-1"
|
||||
>
|
||||
<span className="h-px flex-1 bg-gray-200 dark:bg-white/10" />
|
||||
<span className="rounded-full bg-white px-3 py-1 text-[0.6875rem] font-semibold text-gray-500 shadow-sm ring-1 ring-gray-200 dark:bg-gray-900 dark:text-gray-400 dark:ring-white/10">
|
||||
{dateLabel}
|
||||
</span>
|
||||
<span className="h-px flex-1 bg-gray-200 dark:bg-white/10" />
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
|
||||
<div
|
||||
className={classNames(
|
||||
ownMessage ? 'justify-end' : 'justify-start',
|
||||
'flex items-end gap-2',
|
||||
)}
|
||||
>
|
||||
{!ownMessage && (
|
||||
<Avatar
|
||||
src={message.sender.avatar}
|
||||
@ -2064,7 +2132,8 @@ export default function ChatPage({ currentUser }: ChatPageProps) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
)
|
||||
})}
|
||||
{showDirectTypingIndicator && (
|
||||
|
||||
@ -33,6 +33,7 @@ type NotificationSettings = {
|
||||
deviceJournals: boolean
|
||||
systemMessages: boolean
|
||||
chatMessages: boolean
|
||||
channelMessages: boolean
|
||||
desktopEnabled: boolean
|
||||
}
|
||||
|
||||
@ -47,6 +48,7 @@ const defaultSettings: NotificationSettings = {
|
||||
deviceJournals: true,
|
||||
systemMessages: true,
|
||||
chatMessages: true,
|
||||
channelMessages: true,
|
||||
desktopEnabled: false,
|
||||
}
|
||||
|
||||
@ -293,7 +295,7 @@ export default function Benachrichtigungen() {
|
||||
|
||||
updateSetting('desktopEnabled', true)
|
||||
new Notification('TEG-Benachrichtigungen aktiviert', {
|
||||
body: 'Neue Chatnachrichten können jetzt auf Windows-Ebene angezeigt werden.',
|
||||
body: 'Neue Chat- und Channel-Nachrichten können jetzt auf Windows-Ebene angezeigt werden.',
|
||||
})
|
||||
}
|
||||
|
||||
@ -406,7 +408,7 @@ export default function Benachrichtigungen() {
|
||||
<NotificationCard
|
||||
icon={<EnvelopeIcon aria-hidden="true" className="size-5" />}
|
||||
title="Windows-Benachrichtigungen"
|
||||
description="Zeigt neue Chatnachrichten außerhalb des Browserfensters an."
|
||||
description="Zeigt neue Chat- und Channel-Nachrichten außerhalb des Browserfensters an."
|
||||
>
|
||||
<Switch
|
||||
checked={settings.desktopEnabled}
|
||||
@ -449,6 +451,15 @@ export default function Benachrichtigungen() {
|
||||
description="Zeigt eine Browser-Schnellantwort bei neuen Team- und Direktnachrichten."
|
||||
/>
|
||||
|
||||
<Switch
|
||||
checked={settings.channelMessages}
|
||||
onChange={(event) =>
|
||||
updateSetting('channelMessages', event.target.checked)
|
||||
}
|
||||
label="Channel-Nachrichten"
|
||||
description="Zeigt eine Browser-Benachrichtigung bei neuen Meldungen aus Channels."
|
||||
/>
|
||||
|
||||
<Switch
|
||||
checked={settings.operationUpdates}
|
||||
onChange={(event) =>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user