diff --git a/frontend/README-SETUP.md b/frontend/README-SETUP.md
deleted file mode 100644
index 2f30baa2..00000000
--- a/frontend/README-SETUP.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Libredesk Frontend - Multi-App Setup
-
-This frontend supports both the main Libredesk application and a chat widget as separate Vue applications sharing common UI components.
-
-## Project Structure
-
-```
-frontend/
-├── apps/
-│ ├── main/ # Main Libredesk application
-│ │ ├── src/
-│ │ └── index.html
-│ └── widget/ # Chat widget application
-│ ├── src/
-│ └── index.html
-├── shared-ui/ # Shared UI components (shadcn/ui)
-│ ├── components/
-│ │ └── ui/ # shadcn/ui components
-│ ├── lib/ # Utility functions
-│ └── assets/ # Shared styles
-└── package.json
-```
-
-## Development
-
-Check Makefile for available commands.
-
-## Shared UI Components
-
-The `shared-ui` directory contains all the shadcn/ui components that can be used in both apps.
-
-### Using Shared Components
-
-```vue
-
-
-
-
-
- Example Card
-
-
-
-
-
-
-
-```
-
-### Path Aliases
-
-- `@shared-ui` - Points to the shared-ui directory
-- `@main` - Points to apps/main/src
-- `@widget` - Points to apps/widget/src
-- `@` - Points to the current app's src directory (context-dependent)
diff --git a/frontend/apps/main/src/features/conversation/message/MessageBubble.vue b/frontend/apps/main/src/features/conversation/message/MessageBubble.vue
index df03c310..77a407cf 100644
--- a/frontend/apps/main/src/features/conversation/message/MessageBubble.vue
+++ b/frontend/apps/main/src/features/conversation/message/MessageBubble.vue
@@ -19,12 +19,6 @@
{{ getFullName }}
-
-
-
-
- {{ t('globals.terms.participant', 1) }}
-
@@ -206,9 +200,7 @@ const getFullName = computed(() => {
const getAvatar = computed(() => {
if (props.message.author?.avatar_url) return props.message.author.avatar_url
- if (!isOutgoing.value && convStore.current?.contact?.email) {
- return getGravatarUrl(convStore.current.contact.email)
- }
+ if (props.message.author?.email) return getGravatarUrl(props.message.author.email)
return ''
})
diff --git a/internal/conversation/message.go b/internal/conversation/message.go
index 65027a9d..5ac7699b 100644
--- a/internal/conversation/message.go
+++ b/internal/conversation/message.go
@@ -698,12 +698,27 @@ func (m *Manager) ProcessIncomingMessage(in models.IncomingMessage) (models.Mess
return models.Message{}, nil
}
- // Try plus-addressing (resolves both sender + conversation).
+ // Resolve sender and conversation from plus addressing.
senderID, conversationID, conversationUUID, err := m.resolveSender(&in)
if err != nil {
return models.Message{}, err
}
+ // Find or create contact.
+ if senderID == 0 {
+ user := umodels.User{
+ FirstName: in.Contact.FirstName,
+ LastName: in.Contact.LastName,
+ Email: in.Contact.Email,
+ Type: umodels.UserTypeContact,
+ }
+ if err := m.userStore.CreateContact(&user); err != nil {
+ return models.Message{}, fmt.Errorf("creating contact: %w", err)
+ }
+ senderID = user.ID
+ in.Contact.ID = senderID
+ }
+
// Match conversation if not already matched by plus-addressing.
var isNewConversation bool
if conversationID == 0 {
@@ -713,29 +728,11 @@ func (m *Manager) ProcessIncomingMessage(in models.IncomingMessage) (models.Mess
}
}
- // Resolve sender with conversation context.
- // For existing conversations, use the conversation's contact when emails match
- // to avoid picking the wrong duplicate contact.
- if senderID == 0 {
- if !isNewConversation && conversationID > 0 {
- conversation, convErr := m.GetConversation(conversationID, "", "")
- if convErr == nil && strings.EqualFold(conversation.Contact.Email.String, in.Contact.Email.String) {
- senderID = conversation.ContactID
- in.Contact.ID = senderID
- }
- }
- // Still no sender - create/find contact by email.
- if senderID == 0 {
- user := umodels.User{
- FirstName: in.Contact.FirstName,
- LastName: in.Contact.LastName,
- Email: in.Contact.Email,
- Type: umodels.UserTypeContact,
- }
- if err := m.userStore.CreateContact(&user); err != nil {
- return models.Message{}, fmt.Errorf("creating contact: %w", err)
- }
- senderID = user.ID
+ // For existing conversations, override sender with the conversation's contact when emails match.
+ if !isNewConversation && conversationID > 0 {
+ conversation, convErr := m.GetConversation(conversationID, "", "")
+ if convErr == nil && strings.EqualFold(conversation.Contact.Email.String, in.Contact.Email.String) {
+ senderID = conversation.ContactID
in.Contact.ID = senderID
}
}