improve reaction interface on message bubbles
This commit is contained in:
Vendored
+21
@@ -659,6 +659,7 @@ body[showing-chat] #chat-page-wrapper {
|
|||||||
}
|
}
|
||||||
.message-bubble {
|
.message-bubble {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: var(--max-content-width);
|
max-width: var(--max-content-width);
|
||||||
}
|
}
|
||||||
@@ -728,6 +729,26 @@ body[showing-chat] #chat-page-wrapper {
|
|||||||
.message-bubble[sentbyuser] .tile.main span {
|
.message-bubble[sentbyuser] .tile.main span {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
.message-bubble > .message-reaction-row {
|
||||||
|
max-width: var(--max-input-width);
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--gap-between-tiles);
|
||||||
|
background: var(--surface);
|
||||||
|
}
|
||||||
|
.message-bubble > .message-reaction-row button {
|
||||||
|
min-height: unset;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--control-padding-compact);
|
||||||
|
gap: 0px;
|
||||||
|
flex: 1 !important;
|
||||||
|
}
|
||||||
|
.message-bubble > .message-reaction-row button[zero] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.message-reaction-row {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
/* src/View/ChatPages/taskPage.css */
|
/* src/View/ChatPages/taskPage.css */
|
||||||
#chat-page > div > #main > #task-page > .pane-wrapper > .pane > .main-content {
|
#chat-page > div > #main > #task-page > .pane-wrapper > .pane > .main-content {
|
||||||
|
|||||||
Vendored
+21
-30
@@ -3943,74 +3943,64 @@
|
|||||||
|
|
||||||
// src/View/Components/messageReactionButton.tsx
|
// src/View/Components/messageReactionButton.tsx
|
||||||
function MessageReactionButton(chatMessageViewModel, content) {
|
function MessageReactionButton(chatMessageViewModel, content) {
|
||||||
|
let audioLabel;
|
||||||
|
let count;
|
||||||
|
let reactionState;
|
||||||
|
let isActive = new State(false);
|
||||||
|
let isZero = new State(true);
|
||||||
function sendReaction() {
|
function sendReaction() {
|
||||||
chatMessageViewModel.sendReaction(content, isActive.value);
|
chatMessageViewModel.sendReaction(content, isActive.value);
|
||||||
}
|
}
|
||||||
function getUsername() {
|
function getUsername() {
|
||||||
return chatMessageViewModel.messagePageViewModel.chatViewModel.settingsViewModel.username.value;
|
return chatMessageViewModel.messagePageViewModel.chatViewModel.settingsViewModel.username.value;
|
||||||
}
|
}
|
||||||
function checkIsHighlighted(mapState) {
|
function checkIsHighlighted() {
|
||||||
return mapState.value.has(getUsername());
|
return reactionState.value.has(getUsername());
|
||||||
}
|
}
|
||||||
let audioLabel;
|
|
||||||
let count;
|
|
||||||
let isActive;
|
|
||||||
switch (content) {
|
switch (content) {
|
||||||
case "\u{1F44D}" /* ThumbsUp */: {
|
case "\u{1F44D}" /* ThumbsUp */: {
|
||||||
audioLabel = translations.chatPage.message.thumbsUpReaction;
|
audioLabel = translations.chatPage.message.thumbsUpReaction;
|
||||||
count = chatMessageViewModel.reactionsThumbsUpCount;
|
count = chatMessageViewModel.reactionsThumbsUpCount;
|
||||||
isActive = createProxyState(
|
reactionState = chatMessageViewModel.reactionsThumbsUp;
|
||||||
[chatMessageViewModel.reactionsThumbsUp],
|
|
||||||
() => checkIsHighlighted(chatMessageViewModel.reactionsThumbsUp)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "\u2705" /* Check */: {
|
case "\u2705" /* Check */: {
|
||||||
audioLabel = translations.chatPage.message.checkReaction;
|
audioLabel = translations.chatPage.message.checkReaction;
|
||||||
count = chatMessageViewModel.reactionsCheckCount;
|
count = chatMessageViewModel.reactionsCheckCount;
|
||||||
isActive = createProxyState(
|
reactionState = chatMessageViewModel.reactionsCheck;
|
||||||
[chatMessageViewModel.reactionsCheck],
|
|
||||||
() => checkIsHighlighted(chatMessageViewModel.reactionsCheck)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "\u2757\uFE0F" /* Attention */: {
|
case "\u2757\uFE0F" /* Attention */: {
|
||||||
audioLabel = translations.chatPage.message.attentionReaction;
|
audioLabel = translations.chatPage.message.attentionReaction;
|
||||||
count = chatMessageViewModel.reactionsAttentionCount;
|
count = chatMessageViewModel.reactionsAttentionCount;
|
||||||
isActive = createProxyState(
|
reactionState = chatMessageViewModel.reactionsAttention;
|
||||||
[chatMessageViewModel.reactionsAttention],
|
|
||||||
() => checkIsHighlighted(chatMessageViewModel.reactionsAttention)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "\u203C\uFE0F" /* DoubleAttention */: {
|
case "\u203C\uFE0F" /* DoubleAttention */: {
|
||||||
audioLabel = translations.chatPage.message.doubleAttentionReaction;
|
audioLabel = translations.chatPage.message.doubleAttentionReaction;
|
||||||
count = chatMessageViewModel.reactionsDoubleAttentionCount;
|
count = chatMessageViewModel.reactionsDoubleAttentionCount;
|
||||||
isActive = createProxyState(
|
reactionState = chatMessageViewModel.reactionsDoubleAttention;
|
||||||
[chatMessageViewModel.reactionsDoubleAttention],
|
|
||||||
() => checkIsHighlighted(
|
|
||||||
chatMessageViewModel.reactionsDoubleAttention
|
|
||||||
)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "\u2753" /* Question */: {
|
case "\u2753" /* Question */: {
|
||||||
audioLabel = translations.chatPage.message.questionReaction;
|
audioLabel = translations.chatPage.message.questionReaction;
|
||||||
count = chatMessageViewModel.reactionsQuestionCount;
|
count = chatMessageViewModel.reactionsQuestionCount;
|
||||||
isActive = createProxyState(
|
reactionState = chatMessageViewModel.reactionsQuestion;
|
||||||
[chatMessageViewModel.reactionsQuestion],
|
|
||||||
() => checkIsHighlighted(chatMessageViewModel.reactionsQuestion)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
reactionState.subscribe(() => {
|
||||||
|
isActive.value = checkIsHighlighted();
|
||||||
|
isZero.value = reactionState.value.size == 0;
|
||||||
|
});
|
||||||
return /* @__PURE__ */ createElement(
|
return /* @__PURE__ */ createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
class: "flex",
|
class: "flex",
|
||||||
"on:click": sendReaction,
|
"on:click": sendReaction,
|
||||||
"aria-label": audioLabel,
|
"aria-label": audioLabel,
|
||||||
"toggle:selected": isActive
|
"toggle:selected": isActive,
|
||||||
|
"toggle:zero": isZero
|
||||||
},
|
},
|
||||||
content,
|
content,
|
||||||
/* @__PURE__ */ createElement("span", { "subscribe:innerText": count })
|
/* @__PURE__ */ createElement("span", { "subscribe:innerText": count })
|
||||||
@@ -4019,7 +4009,7 @@
|
|||||||
|
|
||||||
// src/View/Components/messageReactionButtonRow.tsx
|
// src/View/Components/messageReactionButtonRow.tsx
|
||||||
function MessageReactionButtonRow(chatMessageViewModel) {
|
function MessageReactionButtonRow(chatMessageViewModel) {
|
||||||
return /* @__PURE__ */ createElement("div", { class: "flex-row gap" }, MessageReactionButton(
|
return /* @__PURE__ */ createElement("div", { class: "grid gap width-100 message-reaction-row" }, MessageReactionButton(
|
||||||
chatMessageViewModel,
|
chatMessageViewModel,
|
||||||
"\u{1F44D}" /* ThumbsUp */
|
"\u{1F44D}" /* ThumbsUp */
|
||||||
), MessageReactionButton(
|
), MessageReactionButton(
|
||||||
@@ -4090,7 +4080,7 @@
|
|||||||
class: "icon",
|
class: "icon",
|
||||||
"subscribe:innerText": statusIcon
|
"subscribe:innerText": statusIcon
|
||||||
}
|
}
|
||||||
), chatMessageViewModel.dateSent), MessageReactionButtonRow(chatMessageViewModel)), /* @__PURE__ */ createElement("div", { class: "button-container" }, /* @__PURE__ */ createElement(
|
), chatMessageViewModel.dateSent)), /* @__PURE__ */ createElement("div", { class: "button-container" }, /* @__PURE__ */ createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
"on:click": chatMessageViewModel.showInfoModal,
|
"on:click": chatMessageViewModel.showInfoModal,
|
||||||
@@ -4098,6 +4088,7 @@
|
|||||||
},
|
},
|
||||||
/* @__PURE__ */ createElement("span", { class: "icon" }, "info")
|
/* @__PURE__ */ createElement("span", { class: "icon" }, "info")
|
||||||
))),
|
))),
|
||||||
|
MessageReactionButtonRow(chatMessageViewModel),
|
||||||
ChatMessageInfoModal(chatMessageViewModel)
|
ChatMessageInfoModal(chatMessageViewModel)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
@@ -288,6 +288,7 @@ SIZES
|
|||||||
|
|
||||||
/* padding */
|
/* padding */
|
||||||
--control-padding: 1rem;
|
--control-padding: 1rem;
|
||||||
|
--control-padding-compact: .4rem .8rem;
|
||||||
--control-marker-padding: 0.7rem;
|
--control-marker-padding: 0.7rem;
|
||||||
--content-padding: 1rem;
|
--content-padding: 1rem;
|
||||||
--modal-padding: 1.25rem;
|
--modal-padding: 1.25rem;
|
||||||
|
|||||||
@@ -75,6 +75,7 @@
|
|||||||
|
|
||||||
.message-bubble {
|
.message-bubble {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: var(--max-content-width);
|
max-width: var(--max-content-width);
|
||||||
}
|
}
|
||||||
@@ -166,3 +167,28 @@
|
|||||||
.message-bubble[sentbyuser] .tile.main span {
|
.message-bubble[sentbyuser] .tile.main span {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-bubble > .message-reaction-row {
|
||||||
|
max-width: var(--max-input-width);
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
padding: var(--gap-between-tiles);
|
||||||
|
background: var(--surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble > .message-reaction-row button {
|
||||||
|
min-height: unset;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--control-padding-compact);
|
||||||
|
gap: 0px;
|
||||||
|
flex: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble > .message-reaction-row button[zero] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-reaction-row {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
|
||||||
|
}
|
||||||
@@ -44,8 +44,6 @@ export function ChatMessage(chatMessageViewModel: ChatMessageViewModel) {
|
|||||||
></span>
|
></span>
|
||||||
{chatMessageViewModel.dateSent}
|
{chatMessageViewModel.dateSent}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{MessageReactionButtonRow(chatMessageViewModel)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
@@ -59,8 +57,9 @@ export function ChatMessage(chatMessageViewModel: ChatMessageViewModel) {
|
|||||||
<span class="icon">info</span>
|
<span class="icon">info</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{MessageReactionButtonRow(chatMessageViewModel)}
|
||||||
{ChatMessageInfoModal(chatMessageViewModel)}
|
{ChatMessageInfoModal(chatMessageViewModel)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from "bloatless-react";
|
import * as React from "bloatless-react";
|
||||||
import { ReactionSymbols } from "../../Model/Chat/chatModel";
|
import { ChatMessageReaction, ReactionSymbols } from "../../Model/Chat/chatModel";
|
||||||
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||||
import { translations } from "../translations";
|
import { translations } from "../translations";
|
||||||
|
|
||||||
@@ -7,6 +7,12 @@ export function MessageReactionButton(
|
|||||||
chatMessageViewModel: ChatMessageViewModel,
|
chatMessageViewModel: ChatMessageViewModel,
|
||||||
content: ReactionSymbols,
|
content: ReactionSymbols,
|
||||||
) {
|
) {
|
||||||
|
let audioLabel: string;
|
||||||
|
let count: React.State<number>;
|
||||||
|
let reactionState: React.MapState<ChatMessageReaction>;
|
||||||
|
let isActive = new React.State(false);
|
||||||
|
let isZero = new React.State(true);
|
||||||
|
|
||||||
function sendReaction() {
|
function sendReaction() {
|
||||||
chatMessageViewModel.sendReaction(content, isActive.value);
|
chatMessageViewModel.sendReaction(content, isActive.value);
|
||||||
}
|
}
|
||||||
@@ -16,74 +22,55 @@ export function MessageReactionButton(
|
|||||||
.settingsViewModel.username.value;
|
.settingsViewModel.username.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIsHighlighted(mapState: React.MapState<any>): boolean {
|
function checkIsHighlighted(): boolean {
|
||||||
return mapState.value.has(getUsername());
|
return reactionState.value.has(getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
let audioLabel: string;
|
|
||||||
let count: React.State<number>;
|
|
||||||
let isActive: React.State<boolean>;
|
|
||||||
|
|
||||||
switch (content) {
|
switch (content) {
|
||||||
case ReactionSymbols.ThumbsUp: {
|
case ReactionSymbols.ThumbsUp: {
|
||||||
audioLabel = translations.chatPage.message.thumbsUpReaction;
|
audioLabel = translations.chatPage.message.thumbsUpReaction;
|
||||||
count = chatMessageViewModel.reactionsThumbsUpCount;
|
count = chatMessageViewModel.reactionsThumbsUpCount;
|
||||||
isActive = React.createProxyState(
|
reactionState = chatMessageViewModel.reactionsThumbsUp;
|
||||||
[chatMessageViewModel.reactionsThumbsUp],
|
|
||||||
() =>
|
|
||||||
checkIsHighlighted(chatMessageViewModel.reactionsThumbsUp),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ReactionSymbols.Check: {
|
case ReactionSymbols.Check: {
|
||||||
audioLabel = translations.chatPage.message.checkReaction;
|
audioLabel = translations.chatPage.message.checkReaction;
|
||||||
count = chatMessageViewModel.reactionsCheckCount;
|
count = chatMessageViewModel.reactionsCheckCount;
|
||||||
isActive = React.createProxyState(
|
reactionState = chatMessageViewModel.reactionsCheck;
|
||||||
[chatMessageViewModel.reactionsCheck],
|
|
||||||
() => checkIsHighlighted(chatMessageViewModel.reactionsCheck),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ReactionSymbols.Attention: {
|
case ReactionSymbols.Attention: {
|
||||||
audioLabel = translations.chatPage.message.attentionReaction;
|
audioLabel = translations.chatPage.message.attentionReaction;
|
||||||
count = chatMessageViewModel.reactionsAttentionCount;
|
count = chatMessageViewModel.reactionsAttentionCount;
|
||||||
isActive = React.createProxyState(
|
reactionState = chatMessageViewModel.reactionsAttention;
|
||||||
[chatMessageViewModel.reactionsAttention],
|
|
||||||
() =>
|
|
||||||
checkIsHighlighted(chatMessageViewModel.reactionsAttention),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ReactionSymbols.DoubleAttention: {
|
case ReactionSymbols.DoubleAttention: {
|
||||||
audioLabel = translations.chatPage.message.doubleAttentionReaction;
|
audioLabel = translations.chatPage.message.doubleAttentionReaction;
|
||||||
count = chatMessageViewModel.reactionsDoubleAttentionCount;
|
count = chatMessageViewModel.reactionsDoubleAttentionCount;
|
||||||
isActive = React.createProxyState(
|
reactionState = chatMessageViewModel.reactionsDoubleAttention;
|
||||||
[chatMessageViewModel.reactionsDoubleAttention],
|
|
||||||
() =>
|
|
||||||
checkIsHighlighted(
|
|
||||||
chatMessageViewModel.reactionsDoubleAttention,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ReactionSymbols.Question: {
|
case ReactionSymbols.Question: {
|
||||||
audioLabel = translations.chatPage.message.questionReaction;
|
audioLabel = translations.chatPage.message.questionReaction;
|
||||||
count = chatMessageViewModel.reactionsQuestionCount;
|
count = chatMessageViewModel.reactionsQuestionCount;
|
||||||
isActive = React.createProxyState(
|
reactionState = chatMessageViewModel.reactionsQuestion;
|
||||||
[chatMessageViewModel.reactionsQuestion],
|
|
||||||
() =>
|
|
||||||
checkIsHighlighted(chatMessageViewModel.reactionsQuestion),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reactionState.subscribe(() => {
|
||||||
|
isActive.value = checkIsHighlighted();
|
||||||
|
isZero.value = reactionState.value.size == 0;
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
class="flex"
|
class="flex"
|
||||||
on:click={sendReaction}
|
on:click={sendReaction}
|
||||||
aria-label={audioLabel}
|
aria-label={audioLabel}
|
||||||
toggle:selected={isActive}
|
toggle:selected={isActive}
|
||||||
|
toggle:zero={isZero}
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
<span subscribe:innerText={count}></span>
|
<span subscribe:innerText={count}></span>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function MessageReactionButtonRow(
|
|||||||
chatMessageViewModel: ChatMessageViewModel,
|
chatMessageViewModel: ChatMessageViewModel,
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<div class="flex-row gap">
|
<div class="grid gap width-100 message-reaction-row">
|
||||||
{MessageReactionButton(
|
{MessageReactionButton(
|
||||||
chatMessageViewModel,
|
chatMessageViewModel,
|
||||||
ReactionSymbols.ThumbsUp,
|
ReactionSymbols.ThumbsUp,
|
||||||
|
|||||||
Reference in New Issue
Block a user