Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
W
WebFront
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
websystem
WebFront
Commits
5030d371
Commit
5030d371
authored
8 months ago
by
심재엽
Browse files
Options
Downloads
Patches
Plain Diff
design: 채팅방 내부 디자인 변경, 스크롤 추가, 버튼 컴포넌트 디자인 추가
parent
8a708028
No related branches found
No related tags found
1 merge request
!44
[design] 채팅방 내부 디자인 변경, 스크롤 추가, 버튼 컴포넌트 디자인 추가
Pipeline
#10996
passed
8 months ago
Stage: build
Changes
1
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/components/ChattingDetail.jsx
+168
-66
168 additions, 66 deletions
src/components/ChattingDetail.jsx
with
168 additions
and
66 deletions
src/components/ChattingDetail.jsx
+
168
−
66
View file @
5030d371
...
@@ -767,6 +767,28 @@ function ChattingDetail() {
...
@@ -767,6 +767,28 @@ function ChattingDetail() {
// eslint-disable-next-line react-hooks/exhaustive-deps
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
chatRoomId
]);
// chatRoomId 변경 또는 컴포넌트 언마운트 시 실행
},
[
chatRoomId
]);
// chatRoomId 변경 또는 컴포넌트 언마운트 시 실행
useEffect
(()
=>
{
const
lastMessage
=
messages
[
messages
.
length
-
1
];
localStorage
.
setItem
(
`loadedPreviousMessages-
${
chatRoomId
}
`
,
"
true
"
);
const
hasLoadedPreviousMessages
=
localStorage
.
getItem
(
`loadedPreviousMessages-
${
chatRoomId
}
`
);
if
(
!
hasLoadedPreviousMessages
&&
lastMessage
&&
lastMessage
.
type
===
"
previousMessages
"
)
{
return
;
// 이전 메시지일 경우 자동 스크롤 방지
}
// 새 메시지 수신 시 자동으로 아래로 스크롤
if
(
lastMessage
&&
lastMessage
.
type
===
"
message
"
&&
messagesEndRef
.
current
)
{
messagesEndRef
.
current
.
scrollIntoView
({
behavior
:
"
smooth
"
});
}
},
[
messages
,
chatRoomId
]);
const
highlightSearchTerm
=
(
message
)
=>
{
const
highlightSearchTerm
=
(
message
)
=>
{
if
(
!
searchTerm
)
return
message
;
if
(
!
searchTerm
)
return
message
;
...
@@ -794,9 +816,7 @@ function ChattingDetail() {
...
@@ -794,9 +816,7 @@ function ChattingDetail() {
theme
=
"pink"
theme
=
"pink"
icon
=
{
<
FaSearch
/>
}
icon
=
{
<
FaSearch
/>
}
onClick
=
{
toggleSearchBar
}
onClick
=
{
toggleSearchBar
}
>
></
Button
>
</
Button
>
</
ChatRoomHeader
>
</
ChatRoomHeader
>
{
/* 공지사항 */
}
{
/* 공지사항 */
}
...
@@ -807,9 +827,7 @@ function ChattingDetail() {
...
@@ -807,9 +827,7 @@ function ChattingDetail() {
<
NoticeMessage
isCollapsed
=
{
isNoticeCollapsed
}
onClick
=
{
handleNoticeClick
}
>
<
NoticeMessage
isCollapsed
=
{
isNoticeCollapsed
}
onClick
=
{
handleNoticeClick
}
>
📢
{
notice
?.
message
}
📢
{
notice
?.
message
}
</
NoticeMessage
>
</
NoticeMessage
>
<
NoticeSender
>
<
NoticeSender
>
{
notice
?.
sender
}
</
NoticeSender
>
{
notice
?.
sender
}
</
NoticeSender
>
<
NoticeActions
>
<
NoticeActions
>
<
button
onClick
=
{
handleNoticeCollapse
}
>
접어두기
</
button
>
<
button
onClick
=
{
handleNoticeCollapse
}
>
접어두기
</
button
>
<
button
onClick
=
{
handleDismissNotice
}
>
다시 열지 않음
</
button
>
<
button
onClick
=
{
handleDismissNotice
}
>
다시 열지 않음
</
button
>
...
@@ -864,27 +882,38 @@ function ChattingDetail() {
...
@@ -864,27 +882,38 @@ function ChattingDetail() {
onChange
=
{
(
e
)
=>
setSearchTerm
(
e
.
target
.
value
)
}
onChange
=
{
(
e
)
=>
setSearchTerm
(
e
.
target
.
value
)
}
onKeyPress
=
{
handleSearch
}
onKeyPress
=
{
handleSearch
}
placeholder
=
"대화 내용 검색"
placeholder
=
"대화 내용 검색"
className
=
"flex-[1.2] px-4 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 mr-3"
/>
/>
<
div
className
=
"arrow-buttons"
>
<
div
className
=
"flex items-center space-x-1"
>
<
FaArrowUp
<
Button
size
=
"sm"
theme
=
"purple"
onClick
=
{
handleArrowUp
}
onClick
=
{
handleArrowUp
}
size
=
{
20
}
state
=
{
currentSearchIndex
>
0
?
"
default
"
:
"
disable
"
}
style
=
{
{
pointerEvents
:
currentSearchIndex
>
0
?
'
auto
'
:
'
none
'
,
opacity
:
currentSearchIndex
>
0
?
1
:
0.5
}
}
icon
=
{
<
FaArrowUp
/>
}
/>
/>
<
FaArrowDown
<
Button
size
=
"sm"
theme
=
"purple"
onClick
=
{
handleArrowDown
}
onClick
=
{
handleArrowDown
}
size
=
{
20
}
state
=
{
style
=
{
{
currentSearchIndex
<
searchResults
.
length
-
1
?
"
default
"
:
"
disable
"
pointerEvents
:
currentSearchIndex
<
searchResults
.
length
-
1
?
'
auto
'
:
'
none
'
,
}
opacity
:
currentSearchIndex
<
searchResults
.
length
-
1
?
1
:
0.5
,
icon
=
{
<
FaArrowDown
/>
}
}
}
/>
/>
<
Button
size
=
"sm"
theme
=
"black"
onClick
=
{
()
=>
{
setSearchTerm
(
""
);
setSearchResults
([]);
setCurrentSearchIndex
(
0
);
setIsSearching
(
false
);
}
}
>
닫기
</
Button
>
</
div
>
</
div
>
{
searchResults
.
length
===
0
&&
(
<
p
style
=
{
{
color
:
'
gray
'
,
fontSize
:
'
0.9em
'
,
textAlign
:
'
center
'
,
marginTop
:
'
10px
'
}
}
>
더 이상 검색 결과가 없습니다.
</
p
>
)
}
</
FixedSearchBar
>
</
FixedSearchBar
>
)
}
)
}
...
@@ -893,41 +922,105 @@ function ChattingDetail() {
...
@@ -893,41 +922,105 @@ function ChattingDetail() {
<
p
>
메시지가 없습니다.
</
p
>
<
p
>
메시지가 없습니다.
</
p
>
)
:
(
)
:
(
messages
.
map
((
messageData
,
index
)
=>
{
messages
.
map
((
messageData
,
index
)
=>
{
const
isMine
=
messageData
.
sender
===
loggedInUser
;
const
prevMessage
=
messages
[
index
-
1
];
const
nextMessage
=
messages
[
index
+
1
];
// 이전 메시지와 비교
const
sameSenderAsPrev
=
prevMessage
&&
prevMessage
.
sender
===
messageData
.
sender
;
// 다음 메시지와 비교
const
sameSenderAsNext
=
nextMessage
&&
nextMessage
.
sender
===
messageData
.
sender
;
// 현재 메시지의 타임스탬프
const
messageTime
=
new
Date
(
messageData
.
timestamp
).
toLocaleTimeString
([],
{
hour
:
"
2-digit
"
,
minute
:
"
2-digit
"
,
});
// 이전 메시지의 타임스탬프
const
prevMessageTime
=
prevMessage
&&
new
Date
(
prevMessage
.
timestamp
).
toLocaleTimeString
([],
{
hour
:
"
2-digit
"
,
minute
:
"
2-digit
"
,
});
// 새로운 분 단위 메시지인지 확인
const
isNewMinute
=
!
prevMessage
||
messageTime
!==
prevMessageTime
;
// 마지막 메시지인지 확인
const
isLastMessageInGroup
=
!
sameSenderAsNext
||
messageTime
!==
nextMessage
.
timestamp
;
if
(
messageData
.
type
===
"
join
"
||
messageData
.
type
===
"
leave
"
)
{
if
(
messageData
.
type
===
"
join
"
||
messageData
.
type
===
"
leave
"
)
{
return
(
return
(
<
CenteredMessage
key
=
{
index
}
>
{
messageData
.
message
}
</
CenteredMessage
>
<
CenteredMessage
key
=
{
index
}
>
{
messageData
.
message
}
</
CenteredMessage
>
);
);
}
}
// 읽지 않은 사람 수
const
unreadCountValue
=
unreadCount
(
messageData
.
_id
);
return
(
return
(
<
div
key
=
{
index
}
>
{
isNewMinute
&&
!
isMine
&&
(
<
strong
style
=
{
{
display
:
"
block
"
,
marginBottom
:
"
2px
"
,
fontSize
:
"
0.9em
"
,
color
:
"
#555
"
,
}
}
>
{
messageData
.
sender
}
</
strong
>
)
}
<
MessageContainer
<
MessageContainer
key
=
{
index
}
isMine
=
{
isMine
}
isMine
=
{
messageData
.
sender
===
loggedInUser
}
highlighted
=
{
searchResults
[
currentSearchIndex
]
===
messageData
}
highlighted
=
{
searchResults
[
currentSearchIndex
]
===
messageData
}
ref
=
{
ref
=
{
searchResults
[
currentSearchIndex
]
===
messageData
?
highlightedMessageRef
:
null
}
s
earchResults
[
currentSearchIndex
]
===
messageData
s
tyle
=
{
{
?
highlightedMessageRef
marginTop
:
sameSenderAsPrev
?
"
-16px
"
:
"
8px
"
,
:
null
justifyContent
:
isMine
?
"
flex-end
"
:
"
flex-start
"
,
}
}
}
>
>
<
MessageBubble
<
MessageBubble
isMine
=
{
messageData
.
sender
===
loggedInUser
}
isMine
=
{
isMine
}
highlighted
=
{
searchResults
[
currentSearchIndex
]
===
messageData
}
onContextMenu
=
{
(
e
)
=>
handleRightClick
(
e
,
messageData
)
}
onContextMenu
=
{
(
e
)
=>
handleRightClick
(
e
,
messageData
)
}
style
=
{
{
textAlign
:
isMine
?
"
right
"
:
"
left
"
,
}
}
>
<
div
style
=
{
{
display
:
"
flex
"
,
alignItems
:
"
center
"
,
justifyContent
:
isMine
?
"
flex-end
"
:
"
flex-start
"
,
}
}
>
>
<
div
>
{
messageData
.
sender
!==
loggedInUser
&&
(
<
strong
>
{
messageData
.
sender
}
</
strong
>
)
}
{
highlightSearchTerm
(
messageData
.
message
)
}
{
highlightSearchTerm
(
messageData
.
message
)
}
<
span
style
=
{
{
marginLeft
:
isMine
?
"
0
"
:
"
16px
"
,
marginRight
:
isMine
?
"
16px
"
:
"
0
"
,
fontSize
:
"
0.8em
"
,
color
:
"
gray
"
,
}
}
>
{
unreadCountValue
>
0
&&
`
${
unreadCountValue
}
`
}
</
span
>
</
div
>
</
div
>
<
MessageTimestamp
isMine
=
{
messageData
.
sender
===
loggedInUser
}
>
{
isLastMessageInGroup
&&
(
{
new
Date
(
messageData
.
timestamp
).
toLocaleTimeString
()
}
<
MessageTimestamp
isMine
=
{
isMine
}
>
<
span
>
{
` (
${
unreadCount
(
{
messageTime
}
messageData
.
_id
)}
명이 읽지 않음)`
}
</
span
>
</
MessageTimestamp
>
</
MessageTimestamp
>
)
}
</
MessageBubble
>
</
MessageBubble
>
</
MessageContainer
>
</
MessageContainer
>
</
div
>
);
);
})
})
)
}
)
}
...
@@ -941,8 +1034,17 @@ function ChattingDetail() {
...
@@ -941,8 +1034,17 @@ function ChattingDetail() {
onChange
=
{
(
e
)
=>
setInput
(
e
.
target
.
value
)
}
onChange
=
{
(
e
)
=>
setInput
(
e
.
target
.
value
)
}
placeholder
=
"메시지를 입력하세요"
placeholder
=
"메시지를 입력하세요"
onKeyPress
=
{
(
e
)
=>
e
.
key
===
"
Enter
"
&&
sendMessage
()
}
onKeyPress
=
{
(
e
)
=>
e
.
key
===
"
Enter
"
&&
sendMessage
()
}
className
=
"flex-1 px-4 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500"
/>
/>
<
button
onClick
=
{
sendMessage
}
>
전송
</
button
>
<
Button
size
=
"lg"
theme
=
"pink"
state
=
{
input
.
trim
()
?
"
default
"
:
"
disable
"
}
onClick
=
{
sendMessage
}
className
=
"ml-3"
>
전송
</
Button
>
</
ChatRoomInput
>
</
ChatRoomInput
>
</
ChatRoomContainer
>
</
ChatRoomContainer
>
);
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment