@linktr.ee/messaging-react 1.14.1 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.14.1",
3
+ "version": "1.15.0",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -5,10 +5,11 @@ import {
5
5
  ProhibitInsetIcon,
6
6
  SignOutIcon,
7
7
  SpinnerGapIcon,
8
+ StarIcon,
8
9
  } from '@phosphor-icons/react'
9
10
  import classNames from 'classnames'
10
11
  import React, { useState, useCallback, useRef, useEffect } from 'react'
11
- import { Channel as ChannelType, ChannelMemberResponse } from 'stream-chat'
12
+ import { Channel as ChannelType, ChannelMemberResponse, Event } from 'stream-chat'
12
13
  import {
13
14
  Channel,
14
15
  Window,
@@ -65,20 +66,49 @@ const CustomChannelHeader: React.FC<{
65
66
  participant?.user?.name || participant?.user?.id || 'Unknown member'
66
67
  const participantImage = participant?.user?.image
67
68
 
69
+ const [isStarred, setIsStarred] = useState(!!channel.state.membership?.pinned_at)
70
+
71
+ useEffect(() => {
72
+ const handleMemberUpdate = (event: Event) => {
73
+ setIsStarred(event?.member ? !!event.member.pinned_at : !!channel.state.membership?.pinned_at)
74
+ }
75
+
76
+ channel.on('member.updated', handleMemberUpdate)
77
+
78
+ return () => {
79
+ channel.off('member.updated', handleMemberUpdate)
80
+ }
81
+ }, [channel])
82
+
83
+ const handleStarClick = async () => {
84
+ try {
85
+ if (isStarred) {
86
+ await channel.unpin()
87
+ } else {
88
+ await channel.pin()
89
+ }
90
+ } catch (error) {
91
+ console.error('[CustomChannelHeader] Failed to update pinned status:', error)
92
+ }
93
+ }
94
+
68
95
  return (
69
96
  <div className="@container">
70
97
  <div className="flex justify-between items-center @lg:hidden">
71
- <button
72
- className={classNames(
73
- 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center',
74
- !showBackButton && 'invisible'
75
- )}
76
- onClick={onBack || (() => {})}
77
- type="button"
78
- aria-label="Back to conversations"
79
- >
80
- <ArrowLeftIcon className="size-5 text-black/90" />
81
- </button>
98
+ <div className="flex items-center gap-2">
99
+ <button
100
+ className={classNames(
101
+ 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center',
102
+ !showBackButton && 'invisible'
103
+ )}
104
+ onClick={onBack || (() => {})}
105
+ type="button"
106
+ aria-label="Back to conversations"
107
+ >
108
+ <ArrowLeftIcon className="size-5 text-black/90" />
109
+ </button>
110
+ <div className="size-10" />
111
+ </div>
82
112
  <div className="flex flex-col gap-1 items-center">
83
113
  <Avatar
84
114
  id={participant?.user?.id || channel.id || 'unknown'}
@@ -90,16 +120,27 @@ const CustomChannelHeader: React.FC<{
90
120
  {participantName}
91
121
  </h1>
92
122
  </div>
93
- <button
94
- className={classNames(
95
- 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center'
96
- )}
97
- onClick={onShowInfo}
98
- type="button"
99
- aria-label="Show info"
100
- >
101
- <DotsThreeIcon className="size-5 text-black/90" />
102
- </button>
123
+ <div className="flex items-center gap-2">
124
+ <button
125
+ className="size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center"
126
+ onClick={handleStarClick}
127
+ type="button"
128
+ aria-label={isStarred ? 'Unstar conversation' : 'Star conversation'}
129
+ >
130
+ <StarIcon
131
+ className="size-5 text-black/90"
132
+ weight={isStarred ? 'fill' : 'regular'}
133
+ />
134
+ </button>
135
+ <button
136
+ className="size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center"
137
+ onClick={onShowInfo}
138
+ type="button"
139
+ aria-label="Show info"
140
+ >
141
+ <DotsThreeIcon className="size-5 text-black/90" />
142
+ </button>
143
+ </div>
103
144
  </div>
104
145
  <div className="hidden @lg:flex items-center justify-between gap-3 min-h-12">
105
146
  <div className="flex items-center gap-4 min-w-0">
@@ -126,16 +167,29 @@ const CustomChannelHeader: React.FC<{
126
167
  </h1>
127
168
  </div>
128
169
  </div>
129
- {canShowInfo && onShowInfo && (
170
+ <div className="flex items-center gap-2">
130
171
  <button
131
- className={classNames(
132
- 'size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center'
133
- )}
134
- onClick={onShowInfo}
172
+ className="size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center"
173
+ onClick={handleStarClick}
174
+ type="button"
175
+ aria-label={isStarred ? 'Unstar conversation' : 'Star conversation'}
135
176
  >
136
- <DotsThreeIcon className="size-5 text-black/90" />
177
+ <StarIcon
178
+ className="size-5 text-black/90"
179
+ weight={isStarred ? 'fill' : 'regular'}
180
+ />
137
181
  </button>
138
- )}
182
+ {canShowInfo && onShowInfo && (
183
+ <button
184
+ className="size-10 rounded-full bg-[#F1F0EE] flex items-center justify-center"
185
+ onClick={onShowInfo}
186
+ type="button"
187
+ aria-label="Show info"
188
+ >
189
+ <DotsThreeIcon className="size-5 text-black/90" />
190
+ </button>
191
+ )}
192
+ </div>
139
193
  </div>
140
194
  </div>
141
195
  )