Compare commits

...

3 Commits

Author SHA1 Message Date
robbis95 0525356a2b Toolbar 2024-04-17 21:26:41 +02:00
Laynester 4a58b16962 darken hex colour 2024-04-17 13:23:44 -04:00
robbis95 6ee4a7ee78 Started chats 2024-04-17 18:57:56 +02:00
12 changed files with 961 additions and 66 deletions

View File

@ -20,6 +20,29 @@ const lightenHexColor = (hex, percent) =>
return '#' + result.padStart(6, '0');
}
const darkenHexColor = (hex, percent) =>
{
// Remove the hash symbol if present
hex = hex.replace(/^#/, '');
// Convert hex to RGB
let r = parseInt(hex.substring(0, 2), 16);
let g = parseInt(hex.substring(2, 4), 16);
let b = parseInt(hex.substring(4, 6), 16);
// Calculate the darkened RGB values
r = Math.round(Math.max(0, r - 255 * percent));
g = Math.round(Math.max(0, g - 255 * percent));
b = Math.round(Math.max(0, b - 255 * percent));
// Convert RGB back to hex
const result = ((r << 16) | (g << 8) | b).toString(16);
// Make sure result has 6 digits
return '#' + result.padStart(6, '0');
};
const generateShades = (colors) =>
{
for (let color in colors)
@ -31,7 +54,8 @@ const generateShades = (colors) =>
for (let i = 0; i < shades.length; i++)
{
let shade = shades[i];
extended[shade] = lightenHexColor(hex, shades[(shades.length - 1 - i) ] / 1000);
extended[shade] = lightenHexColor(hex, shades[(shades.length - 1 - i) ] / 950);
extended[-shade] = darkenHexColor(hex, shades[(shades.length - 1 - i) ] / 950)
}
colors[color] = {
@ -40,6 +64,8 @@ const generateShades = (colors) =>
}
}
console.log(colors)
return colors;
}

853
src/chats.css Normal file
View File

@ -0,0 +1,853 @@
.bubble-container {
transition: top 0.2s ease 0s;
.chat-bubble {
border-image-slice: 17 6 6 29 fill;
border-image-width: 17px 6px 6px 29px;
border-image-outset: 2px 0px 0px 0px;
border-image-repeat: repeat repeat;
&.type-0 {
// normal
.message {
font-weight: 400;
}
}
&.type-1 {
// whisper
.message {
font-weight: 400;
font-style: italic;
color: #595959;
}
}
&.type-2 {
// shout
.message {
font-weight: 700;
}
}
&.bubble-0 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_0_transparent.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');
bottom: -5px;
}
}
&.bubble-1 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_1.png');
border-image-slice: 18 6 6 29 fill;
border-image-width: 18px 6px 6px 29px;
border-image-outset: 3px 0px 0px 0px;
.user-container {
display: none;
}
.username {
display: none;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');
}
}
&.bubble-2,
&.bubble-31 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_2.png');
.user-container {
display: none;
}
.username {
color: rgba($white, 1);
}
.message {
color: rgba($white, 1) !important;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_2_31_pointer.png');
height: 7px;
}
}
&.bubble-3 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_3.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_3_pointer.png');
}
}
&.bubble-4 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_4.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_4_pointer.png');
}
}
&.bubble-5 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_5.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_5_pointer.png');
}
}
&.bubble-6 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_6.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_6_pointer.png');
}
}
&.bubble-7 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_7.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_7_pointer.png');
}
}
&.bubble-8 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_8.png');
border-image-slice: 20 6 6 27 fill;
border-image-width: 20px 6px 6px 27px;
border-image-outset: 5px 0px 0px 0px;
.chat-content {
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_8_pointer.png');
}
}
&.bubble-9 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_9.png');
border-image-slice: 17 18 12 19 fill;
border-image-width: 17px 18px 12px 19px;
border-image-outset: 7px 7px 0px 9px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_9_pointer.png');
width: 7px;
height: 10px;
bottom: -6px;
}
}
&.bubble-10 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_10.png');
border-image-slice: 29 18 8 37 fill;
border-image-width: 29px 18px 8px 37px;
border-image-outset: 12px 7px 1px 5px;
.chat-content {
margin-left: 24px;
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_10_pointer.png');
width: 7px;
height: 8px;
bottom: -3px;
}
}
&.bubble-11 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_11.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_11_pointer.png');
}
}
&.bubble-12 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_12.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_12_pointer.png');
}
}
&.bubble-13 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_13.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_13_pointer.png');
}
}
&.bubble-14 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_14.png');
.chat-content {
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_14_pointer.png');
}
}
&.bubble-15 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_15.png');
.chat-content {
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_15_pointer.png');
}
}
&.bubble-16 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_16.png');
border-image-slice: 13 6 10 31 fill;
border-image-width: 13px 6px 10px 31px;
border-image-outset: 6px 0px 0px 0px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_16_pointer.png');
height: 8px;
}
}
&.bubble-17 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_17.png');
border-image-slice: 24 6 8 35 fill;
border-image-width: 24px 6px 8px 35px;
border-image-outset: 9px 0px 2px 5px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_17_pointer.png');
}
}
&.bubble-18 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_18.png');
border-image-slice: 7 16 8 16 fill;
border-image-width: 7px 16px 8px 16px;
border-image-outset: 3px 10px 2px 11px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_18_pointer.png');
height: 8px;
}
}
&.bubble-19 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_19.png');
border-image-slice: 17 6 9 19 fill;
border-image-width: 17px 6px 9px 19px;
border-image-outset: 5px 0px 0px 8px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_19_20_pointer.png');
}
}
&.bubble-20 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_20.png');
border-image-slice: 18 6 8 19 fill;
border-image-width: 18px 6px 8px 19px;
border-image-outset: 5px 0px 0px 8px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_19_20_pointer.png');
}
}
&.bubble-21 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_21.png');
border-image-slice: 20 6 12 24 fill;
border-image-width: 20px 6px 12px 24px;
border-image-outset: 13px 2px 1px 3px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_21_pointer.png');
bottom: -4px;
}
}
&.bubble-22 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_22.png');
border-image-slice: 18 19 11 33 fill;
border-image-width: 18px 19px 11px 33px;
border-image-outset: 7px 1px 1px 5px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_22_pointer.png');
}
}
&.bubble-23 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_23.png');
border-image-slice: 16 6 7 32 fill;
border-image-width: 16px 6px 7px 32px;
border-image-outset: 5px 0px 0px 3px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_23_37_pointer.png');
}
}
&.bubble-24 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_24.png');
border-image-slice: 23 8 6 40 fill;
border-image-width: 23px 8px 6px 40px;
border-image-outset: 6px 0px 0px 6px;
.chat-content {
margin-left: 30px;
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_24_pointer.png');
bottom: -4px;
}
}
&.bubble-25 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_25.png');
border-image-slice: 10 13 8 28 fill;
border-image-width: 10px 13px 8px 28px;
border-image-outset: 6px 3px 2px 0px;
.chat-content {
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_25_pointer.png');
height: 9px;
bottom: -7px;
}
}
&.bubble-26 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_26.png');
border-image-slice: 16 9 8 29 fill;
border-image-width: 16px 9px 8px 29px;
border-image-outset: 2px 2px 2px 0px;
.chat-content {
color: #c59432;
text-shadow: 1px 1px rgba(0, 0, 0, 0.3);
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_26_pointer.png');
height: 10px;
bottom: -6px;
}
}
&.bubble-27 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_27.png');
border-image-slice: 25 6 5 36 fill;
border-image-width: 25px 6px 5px 36px;
border-image-outset: 8px 0px 0px 5px;
.chat-content {
margin-left: 30px;
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_27_pointer.png');
}
}
&.bubble-28 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_28.png');
border-image-slice: 16 7 7 27 fill;
border-image-width: 16px 7px 7px 27px;
border-image-outset: 3px 0px 0px 0px;
.chat-content {
margin-left: 25px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_28_pointer.png');
}
}
&.bubble-29 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_29.png');
border-image-slice: 10 7 15 31 fill;
border-image-width: 10px 7px 15px 31px;
border-image-outset: 2px 0px 0px 1px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_29_pointer.png');
bottom: -4px;
}
}
&.bubble-30 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_30.png');
.user-container {
display: none;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_30_pointer.png');
height: 7px;
}
}
&.bubble-32 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_32.png');
border-image-slice: 15 7 7 30 fill;
border-image-width: 15px 7px 7px 30px;
border-image-outset: 2px 0px 0px 0px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_32_pointer.png');
}
}
&.bubble-33 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_33_34.png');
border-image-slice: 7 6 6 39 fill;
border-image-width: 7px 6px 6px 39px;
border-image-outset: 2px 0px 0px 0px;
.user-container {
display: none;
}
.chat-content {
margin-left: 35px;
}
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 9px;
top: 2px;
background: url('@/assets/images/chat/chatbubbles/bubble_33_extra.png');
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');
}
}
&.bubble-34 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_33_34.png');
border-image-slice: 7 6 6 39 fill;
border-image-width: 7px 6px 6px 39px;
border-image-outset: 2px 0px 0px 0px;
&.type-1 {
.message {
font-style: unset;
color: inherit;
}
}
.user-container {
display: none;
}
.username {
display: none;
}
.chat-content {
margin-left: 35px;
}
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 9px;
top: 2px;
background: url('@/assets/images/chat/chatbubbles/bubble_34_extra.png');
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');
}
}
&.bubble-35 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_35.png');
border-image-slice: 19 6 5 29 fill;
border-image-width: 19px 6px 5px 29px;
border-image-outset: 4px 0px 0px 0px;
.user-container {
display: none;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_35_pointer.png');
}
}
&.bubble-36 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_36.png');
border-image-slice: 17 7 5 30 fill;
border-image-width: 17px 7px 5px 30px;
border-image-outset: 2px 0px 0px 0px;
.user-container {
display: none;
}
&::before {
content: ' ';
position: absolute;
width: 13px;
height: 18px;
left: 5px;
top: 2px;
background: url('@/assets/images/chat/chatbubbles/bubble_36_extra.png');
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_36_pointer.png');
}
}
&.bubble-37 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_37.png');
border-image-slice: 16 6 7 32 fill;
border-image-width: 16px 6px 7px 32px;
border-image-outset: 5px 0px 0px 3px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_23_37_pointer.png');
}
}
&.bubble-38 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_38.png');
border-image-slice: 17 7 5 30 fill;
border-image-width: 17px 7px 5px 30px;
border-image-outset: 2px 0px 0px 0px;
.user-container {
display: none;
}
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 3px;
top: 2px;
background: url('@/assets/images/chat/chatbubbles/bubble_38_extra.png');
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_38_pointer.png');
}
}
.user-container {
z-index: 3;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
max-height: 24px;
overflow: hidden;
.user-image {
position: absolute;
top: -15px;
left: -9.25px;
width: 45px;
height: 65px;
background-repeat: no-repeat;
background-position: center;
transform: scale(0.5);
overflow: hidden;
image-rendering: initial;
}
}
.chat-content {
padding: 5px 6px 5px 4px;
margin-left: 27px;
line-height: 1;
color: $black;
min-height: 25px;
}
}
}
.chat-bubble-icon {
background-repeat: no-repeat;
background-position: center;
&.bubble-0 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_0.png');
}
&.bubble-1 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_1.png');
height: 25px;
}
&.bubble-2,
&.bubble-31 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_2.png');
}
&.bubble-3 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_3.png');
}
&.bubble-4 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_4.png');
}
&.bubble-5 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_5.png');
}
&.bubble-6 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_6.png');
}
&.bubble-7 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_7.png');
}
&.bubble-8 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_8.png');
}
&.bubble-9 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_9.png');
}
&.bubble-10 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_10.png');
}
&.bubble-11 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_11.png');
}
&.bubble-12 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_12.png');
}
&.bubble-13 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_13.png');
}
&.bubble-14 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_14.png');
}
&.bubble-15 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_15.png');
}
&.bubble-16 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_16.png');
}
&.bubble-17 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_17.png');
}
&.bubble-18 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_18.png');
}
&.bubble-19 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_19.png');
}
&.bubble-20 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_20.png');
}
&.bubble-21 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_21.png');
}
&.bubble-22 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_22.png');
}
&.bubble-23 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_23.png');
}
&.bubble-24 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_24.png');
}
&.bubble-25 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_25.png');
}
&.bubble-26 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_26.png');
}
&.bubble-27 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_27.png');
}
&.bubble-28 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_28.png');
}
&.bubble-29 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_29.png');
}
&.bubble-30 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_30.png');
}
&.bubble-32 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_32.png');
}
&.bubble-33 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_33_34.png');
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 11px;
top: 10px;
background: url('@/assets/images/chat/chatbubbles/bubble_33_extra.png');
}
}
&.bubble-34 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_33_34.png');
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 11px;
top: 10px;
background: url('@/assets/images/chat/chatbubbles/bubble_34_extra.png');
}
}
&.bubble-35 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_35.png');
}
&.bubble-36 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_36.png');
&::before {
content: ' ';
position: absolute;
width: 13px;
height: 18px;
left: 13px;
top: 10px;
background: url('@/assets/images/chat/chatbubbles/bubble_36_extra.png');
}
}
&.bubble-37 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_35.png');
}
&.bubble-38 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_38.png');
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 11px;
top: 10px;
background: url('@/assets/images/chat/chatbubbles/bubble_38_extra.png');
}
}
}

View File

@ -33,26 +33,26 @@ export const FriendBarItemView: FC<{ friend: MessengerFriend }> = props =>
if(!friend)
{
return (
<div ref={ elementRef } className="btn btn-primary friend-bar-item friend-bar-search">
<div className="friend-bar-item-head absolute"/>
<div ref={ elementRef } className="border border-black w-[130px] mx-1 rounded cursor-pointer z-0 text-sm py-2.5 px-1 relative pl-[38px] text-left friend-bar-search">
<div className="absolute friend-bar-item-head"/>
<div className="text-truncate">{ LocalizeText('friend.bar.find.title') }</div>
</div>
);
}
return (
<div ref={ elementRef } className={ 'btn btn-success friend-bar-item ' + (isVisible ? 'friend-bar-item-active' : '') } onClick={ event => setVisible(prevValue => !prevValue) }>
<div className={ `friend-bar-item-head absolute ${ friend.id > 0 ? 'avatar': 'group' }` }>
<div ref={ elementRef } className={ 'border border-black rounded cursor-pointer text-sm w-[130px] mx-1 z-0 py-2.5 px-1 relative pl-[38px] text-left' + (isVisible ? 'mb-[21px]' : '') } onClick={ event => setVisible(prevValue => !prevValue) }>
<div className={ `absolute ${ friend.id > 0 ? 'top-[-30px] left-[-30px]': 'top-0 left-[-5px]' }` }>
{ (friend.id > 0) && <LayoutAvatarImageView direction={ 2 } figure={ friend.figure } headOnly={ true } /> }
{ (friend.id <= 0) && <LayoutBadgeImageView badgeCode={ friend.figure } isGroup={ true } /> }
</div>
<div className="text-truncate">{ friend.name }</div>
<div className="truncate">{ friend.name }</div>
{ isVisible &&
<div className="flex justify-content-between">
<div className="nitro-friends-spritesheet icon-friendbar-chat cursor-pointer" onClick={ event => OpenMessengerChat(friend.id) } />
<div className="cursor-pointer nitro-friends-spritesheet icon-friendbar-chat" onClick={ event => OpenMessengerChat(friend.id) } />
{ friend.followingAllowed &&
<div className="nitro-friends-spritesheet icon-friendbar-visit cursor-pointer" onClick={ event => followFriend(friend) } /> }
<div className="nitro-friends-spritesheet icon-profile cursor-pointer" onClick={ event => GetUserProfile(friend.id) } />
<div className="cursor-pointer nitro-friends-spritesheet icon-friendbar-visit" onClick={ event => followFriend(friend) } /> }
<div className="cursor-pointer nitro-friends-spritesheet icon-profile" onClick={ event => GetUserProfile(friend.id) } />
</div> }
</div>
);

View File

@ -13,12 +13,12 @@ export const FriendBarView: FC<{ onlineFriends: MessengerFriend[] }> = props =>
const elementRef = useRef<HTMLDivElement>();
return (
<div ref={ elementRef } className="flex items-center friend-bar">
<Button className="friend-bar-button" disabled={ (indexOffset <= 0) } variant="black" onClick={ event => setIndexOffset(indexOffset - 1) }>
<div ref={ elementRef } className="flex items-center">
<Button className="z-[2] cursor-pointer" disabled={ (indexOffset <= 0) } variant="black" onClick={ event => setIndexOffset(indexOffset - 1) }>
<FaChevronLeft className="fa-icon" />
</Button>
{ Array.from(Array(MAX_DISPLAY_COUNT), (e, i) => <FriendBarItemView key={ i } friend={ (onlineFriends[ indexOffset + i ] || null) } />) }
<Button className="friend-bar-button" disabled={ !((onlineFriends.length > MAX_DISPLAY_COUNT) && ((indexOffset + MAX_DISPLAY_COUNT) <= (onlineFriends.length - 1))) } variant="black" onClick={ event => setIndexOffset(indexOffset + 1) }>
<Button className="z-[2] cursor-pointer" disabled={ !((onlineFriends.length > MAX_DISPLAY_COUNT) && ((indexOffset + MAX_DISPLAY_COUNT) <= (onlineFriends.length - 1))) } variant="black" onClick={ event => setIndexOffset(indexOffset + 1) }>
<FaChevronRight className="fa-icon" />
</Button>
</div>

View File

@ -44,7 +44,7 @@ export const ChatInputStyleSelectorView: FC<ChatInputStyleSelectorViewProps> = p
return (
<>
<div className="icon chatstyles-icon cursor-pointer" onClick={ toggleSelector } />
<div className="cursor-pointer nitro-icon chatstyles-icon" onClick={ toggleSelector } />
<Overlay placement="top" show={ selectorVisible } target={ target }>
<Popover className="nitro-chat-style-selector-container image-rendering-pixelated">
<NitroCardContentView className="bg-transparent" overflow="hidden">

View File

@ -235,10 +235,10 @@ export const ChatInputView: FC<{}> = props =>
return (
createPortal(
<div className="nitro-chat-input-container">
<div className="input-sizer items-center">
<div className="nitro-chat-input-container flex justify-center items-center relative h-10 border-2 border-black bg-gray-200 pr-2.5 w-full overflow-hidden rounded-lg">
<div className="items-center input-sizer">
{ !floodBlocked &&
<input ref={ inputRef } className="chat-input" maxLength={ maxChatLength } placeholder={ LocalizeText('widgets.chatinput.default') } type="text" value={ chatValue } onChange={ event => updateChatInput(event.target.value) } onMouseDown={ event => setInputFocus() } /> }
<input ref={ inputRef } className="bg-transparent border-none" maxLength={ maxChatLength } placeholder={ LocalizeText('widgets.chatinput.default') } type="text" value={ chatValue } onChange={ event => updateChatInput(event.target.value) } onMouseDown={ event => setInputFocus() } /> }
{ floodBlocked &&
<Text variant="danger">{ LocalizeText('chat.input.alert.flood', [ 'time' ], [ floodBlockedSeconds.toString() ]) } </Text> }
</div>

View File

@ -9,48 +9,50 @@ interface ChatWidgetMessageViewProps
bubbleWidth?: number;
}
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = ({
chat = null,
makeRoom = null,
bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL
}) =>
{
const { chat = null, makeRoom = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL } = props;
const [ isVisible, setIsVisible ] = useState(false);
const [ isReady, setIsReady ] = useState<boolean>(false);
const elementRef = useRef<HTMLDivElement>();
const [ isReady, setIsReady ] = useState(false);
const elementRef = useRef<HTMLDivElement>(null);
const getBubbleWidth = useMemo(() =>
const getBubbleWidth = useMemo(() =>
{
switch(bubbleWidth)
switch(bubbleWidth)
{
case RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL:
return 350;
return 'w-350';
case RoomChatSettings.CHAT_BUBBLE_WIDTH_THIN:
return 240;
return 'w-240';
case RoomChatSettings.CHAT_BUBBLE_WIDTH_WIDE:
return 2000;
return 'w-2000';
default:
return 'w-350';
}
}, [ bubbleWidth ]);
useEffect(() =>
useEffect(() =>
{
setIsVisible(false);
const element = elementRef.current;
if(!element) return;
const width = element.offsetWidth;
const height = element.offsetHeight;
const { offsetWidth: width, offsetHeight: height } = element;
chat.width = width;
chat.height = height;
chat.elementRef = element;
let left = chat.left;
let top = chat.top;
let { left, top } = chat;
if(!left && !top)
if(!left && !top)
{
left = (chat.location.x - (width / 2));
top = (element.parentElement.offsetHeight - height);
top = (element.parentElement!.offsetHeight - height);
chat.left = left;
chat.top = top;
@ -58,37 +60,39 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
setIsReady(true);
return () =>
return () =>
{
chat.elementRef = null;
setIsReady(false);
}
}, [ chat ]);
useEffect(() =>
useEffect(() =>
{
if(!isReady || !chat || isVisible) return;
if (!isReady || !chat || isVisible) return;
if(makeRoom) makeRoom(chat);
if (makeRoom) makeRoom(chat);
setIsVisible(true);
}, [ chat, isReady, isVisible, makeRoom ]);
return (
<div ref={ elementRef } className={ `bubble-container ${ isVisible ? 'visible' : 'invisible' }` } onClick={ event => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT) }>
{ (chat.styleId === 0) &&
<div className="user-container-bg" style={ { backgroundColor: chat.color } } /> }
<div className={ `chat-bubble bubble-${ chat.styleId } type-${ chat.type }` } style={ { maxWidth: getBubbleWidth } }>
<div className="user-container">
{ chat.imageUrl && (chat.imageUrl.length > 0) &&
<div className="user-image" style={ { backgroundImage: `url(${ chat.imageUrl })` } } /> }
<div ref={ elementRef } className={ `bubble-container ${ isVisible ? 'visible' : 'invisible' } w-max absolute select-none pointer-events-auto` }
onClick={ () => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT) }>
{ chat.styleId === 0 && (
<div className="absolute top-[-1px] left-[1px] w-[30px] h-[calc(100%-0.5px)] rounded-[7px] z-[1]" style={ { backgroundColor: chat.color } } />
) }
<div className={ `chat-bubble bubble-${ chat.styleId } ${ getBubbleWidth } relative z-[1] break-words min-h-[26px] text-[14px] max-w-[350px]` }
style={ { maxWidth: getBubbleWidth } }>
<div className="user-container flex items-center justify-center h-full max-h-[24px] overflow-hidden">
{ chat.imageUrl && chat.imageUrl.length > 0 && (
<div className="user-image absolute top-[-15px] left-[-9.25px] w-[45px] h-[65px] bg-no-repeat bg-center scale-50" style={ { backgroundImage: `url(${ chat.imageUrl })` } } />
) }
</div>
<div className="chat-content">
<b className="username mr-1" dangerouslySetInnerHTML={ { __html: `${ chat.username }: ` } } />
<div className="chat-content py-[5px] px-[6px] ml-[27px] leading-[1] min-h-[25px]">
<b className="username" dangerouslySetInnerHTML={ { __html: `${ chat.username }: ` } } />
<span className="message" dangerouslySetInnerHTML={ { __html: `${ chat.formattedText }` } } />
</div>
<div className="pointer" />
<div className="pointer absolute left-[50%] translate-x-[-50%] w-[9px] h-[6px] bottom-[-5px]" />
</div>
</div>
);

View File

@ -155,7 +155,7 @@ export const ChatWidgetView: FC<{}> = props =>
}, [ getScrollSpeed, removeHiddenChats, setChatMessages ]);
return (
<div ref={ elementRef } className="nitro-chat-widget">
<div ref={ elementRef } className="absolute flex justify-center items-center w-full top-0 min-h-[1px] z-[var(--chat-zindex)] bg-transparent rounded-none shadow-none pointer-events-none">
{ chatMessages.map(chat => <ChatWidgetMessageView key={ chat.id } bubbleWidth={ chatSettings.weight } chat={ chat } makeRoom={ makeRoom } />) }
</div>
);

View File

@ -19,46 +19,44 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
const { iconState = MessengerIconState.HIDDEN } = useMessenger();
const isMod = GetSessionDataManager().isModerator;
useMessageEvent<PerkAllowancesMessageEvent>(PerkAllowancesMessageEvent, event =>
useMessageEvent<PerkAllowancesMessageEvent>(PerkAllowancesMessageEvent, event =>
{
const parser = event.getParser();
setUseGuideTool(parser.isAllowed(PerkEnum.USE_GUIDE_TOOL));
setUseGuideTool(event.getParser().isAllowed(PerkEnum.USE_GUIDE_TOOL));
});
useNitroEvent<NitroToolbarAnimateIconEvent>(NitroToolbarAnimateIconEvent.ANIMATE_ICON, event =>
useNitroEvent<NitroToolbarAnimateIconEvent>(NitroToolbarAnimateIconEvent.ANIMATE_ICON, event =>
{
const animationIconToToolbar = (iconName: string, image: HTMLImageElement, x: number, y: number) =>
{
const target = (document.body.getElementsByClassName(iconName)[0] as HTMLElement);
if(!target) return;
image.className = 'toolbar-icon-animation';
image.style.visibility = 'visible';
image.style.left = (x + 'px');
image.style.top = (y + 'px');
document.body.append(image);
const targetBounds = target.getBoundingClientRect();
const imageBounds = image.getBoundingClientRect();
const left = (imageBounds.x - targetBounds.x);
const top = (imageBounds.y - targetBounds.y);
const squared = Math.sqrt(((left * left) + (top * top)));
const wait = (500 - Math.abs(((((1 / squared) * 100) * 500) * 0.5)));
const height = 20;
const motionName = (`ToolbarBouncing[${ iconName }]`);
if(!Motions.getMotionByTag(motionName))
{
Motions.runMotion(new Queue(new Wait((wait + 8)), new DropBounce(target, 400, 12))).tag = motionName;
}
const motion = new Queue(new EaseOut(new JumpBy(image, wait, ((targetBounds.x - imageBounds.x) + height), (targetBounds.y - imageBounds.y), 100, 1), 1), new Dispose(image));
Motions.runMotion(motion);
}
@ -70,7 +68,7 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
<TransitionAnimation inProp={ isMeExpanded } timeout={ 300 } type={ TransitionAnimationTypes.FADE_IN }>
<ToolbarMeView setMeExpanded={ setMeExpanded } unseenAchievementCount={ getTotalUnseen } useGuideTool={ useGuideTool } />
</TransitionAnimation>
<div className="absolute bottom-0 left-0 flex items-center justify-between w-full gap-2 px-3 py-1 z-toolbar bg-toolbar h-toolbar">
<div className="absolute bottom-0 left-0 flex items-center justify-between w-full gap-2 px-3 py-1 border-t border-black z-toolbar bg-toolbar bg-toolbar-gradient shadow-inner1px">
<div className="flex items-center gap-2">
<div className="flex items-center gap-2">
<div className={ classNames('flex justify-center items-center w-[50px] h-[45px] overflow-hidden cursor-pointer *:ml-[-5px] *:mt-[25px]', isMeExpanded && 'active') } onClick={ event => setMeExpanded(!isMeExpanded) }>

View File

@ -212,6 +212,14 @@ body {
.nitro-icon {
@apply inline-block bg-transparent bg-center bg-no-repeat outline-0;
&:hover {
@apply translate-x-[-1px] translate-y-[-1px] drop-shadow-hover
}
&:active {
@apply transform-none filter-none
}
&.icon-nitro-light {
background-image: url("@/assets/images/nitro/nitro-n-light.svg");
}

View File

@ -1,5 +1,6 @@
import { createRoot } from 'react-dom/client';
import { App } from './App';
import './index.css';
import './chats.css';
createRoot(document.getElementById('root')).render(<App />);

View File

@ -34,6 +34,7 @@ module.exports = {
boxShadow,
backgroundImage: {
'button-gradient-gray': 'linear-gradient(to bottom, #e2e2e2 50%, #c8c8c8 50%)',
'toolbar-gradient': 'linear-gradient(to bottom, #363636 50%, #2a2a2a 50%)',
},
spacing: {
'card-header': '33px',
@ -45,7 +46,11 @@ module.exports = {
},
zIndex: {
'toolbar': '',
'loading': '100'
'loading': '100',
'chat-zindex': '20'
},
dropShadow: {
'hover': '2px 2px 0 rgba(0,0,0,0.8)'
},
},
},