Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/chat/chat-indicator.tsx
1496 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
// TODO: for a frame tree it really only makes sense for this button
7
// to always show the chat. For sagews and old stuff it should hide
8
// and show it. But it's very hard to know from here which doc type
9
// this is... so for now it still sort of toggles. For now things
10
// do work properly via a hack in close_chat in project_actions.
11
12
import { filename_extension } from "@cocalc/util/misc";
13
import { Button, Tooltip } from "antd";
14
import { debounce } from "lodash";
15
import { useMemo } from "react";
16
import { FormattedMessage, useIntl } from "react-intl";
17
import { UsersViewing } from "@cocalc/frontend/account/avatar/users-viewing";
18
import { redux, useTypedRedux } from "@cocalc/frontend/app-framework";
19
import { HiddenXS } from "@cocalc/frontend/components";
20
import { Icon } from "@cocalc/frontend/components/icon";
21
import track from "@cocalc/frontend/user-tracking";
22
import { labels } from "../i18n";
23
24
export type ChatState =
25
| "" // not opened (also undefined counts as not open)
26
| "internal" // chat is open and managed internally (via frame tree)
27
| "external" // chat is open and managed externally (e.g., legacy sage worksheet)
28
| "pending"; // chat should be opened when the file itself is actually initialized.
29
30
const CHAT_INDICATOR_STYLE: React.CSSProperties = {
31
fontSize: "15pt",
32
paddingTop: "2px",
33
cursor: "pointer",
34
background: "#e8e8e8",
35
borderTop: "2px solid lightgrey",
36
} as const;
37
38
const USERS_VIEWING_STYLE: React.CSSProperties = {
39
maxWidth: "120px",
40
marginRight: "5px",
41
} as const;
42
43
interface Props {
44
project_id: string;
45
path: string;
46
chatState?: ChatState;
47
}
48
49
export function ChatIndicator({ project_id, path, chatState }: Props) {
50
const style: React.CSSProperties = {
51
...CHAT_INDICATOR_STYLE,
52
...{ display: "flex" },
53
};
54
55
return (
56
<div style={style}>
57
<UsersViewing
58
project_id={project_id}
59
path={path}
60
style={USERS_VIEWING_STYLE}
61
/>
62
<ChatButton project_id={project_id} path={path} chatState={chatState} />
63
</div>
64
);
65
}
66
67
function ChatButton({ project_id, path, chatState }) {
68
const intl = useIntl();
69
70
const toggleChat = debounce(
71
() => {
72
const actions = redux.getProjectActions(project_id);
73
if (chatState) {
74
track("close-chat", { project_id, path, how: "chat-button" });
75
actions.close_chat({ path });
76
} else {
77
track("open-chat", { project_id, path, how: "chat-button" });
78
actions.open_chat({ path });
79
}
80
},
81
1000,
82
{ leading: true },
83
);
84
const fileUse = useTypedRedux("file_use", "file_use");
85
const isNewChat = useMemo(
86
() =>
87
!!redux.getStore("file_use")?.get_file_info(project_id, path)
88
?.is_unseenchat,
89
[fileUse, project_id, path],
90
);
91
92
if (filename_extension(path) === "sage-chat") {
93
// Special case: do not show side chat for chatrooms
94
return null;
95
}
96
97
return (
98
<Tooltip
99
title={
100
<span>
101
<Icon name="comment" style={{ marginRight: "5px" }} />
102
<FormattedMessage
103
id="chat.chat-indicator.tooltip"
104
defaultMessage={"Hide or Show Document Chat"}
105
/>
106
</span>
107
}
108
placement={"leftTop"}
109
mouseEnterDelay={0.5}
110
>
111
<Button
112
type="text"
113
danger={isNewChat}
114
className={isNewChat ? "smc-chat-notification" : undefined}
115
onClick={toggleChat}
116
style={{ background: chatState ? "white" : undefined }}
117
>
118
<Icon name="comment" />
119
<HiddenXS>
120
<span style={{ marginLeft: "5px" }}>
121
{intl.formatMessage(labels.chat)}
122
</span>
123
</HiddenXS>
124
</Button>
125
</Tooltip>
126
);
127
}
128
129