CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/chat/chat-indicator.tsx
Views: 687
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: "3px",
33
cursor: "pointer",
34
} as const;
35
36
const USERS_VIEWING_STYLE: React.CSSProperties = {
37
maxWidth: "120px",
38
marginRight: "5px",
39
} as const;
40
41
interface Props {
42
project_id: string;
43
path: string;
44
chatState?: ChatState;
45
}
46
47
export function ChatIndicator({ project_id, path, chatState }: Props) {
48
const style: React.CSSProperties = {
49
...CHAT_INDICATOR_STYLE,
50
...{ display: "flex" },
51
};
52
53
return (
54
<div style={style}>
55
<UsersViewing
56
project_id={project_id}
57
path={path}
58
style={USERS_VIEWING_STYLE}
59
/>
60
<ChatButton project_id={project_id} path={path} chatState={chatState} />
61
</div>
62
);
63
}
64
65
function ChatButton({ project_id, path, chatState }) {
66
const intl = useIntl();
67
68
const toggleChat = debounce(
69
() => {
70
const actions = redux.getProjectActions(project_id);
71
if (chatState) {
72
track("close-chat", { project_id, path, how: "chat-button" });
73
actions.close_chat({ path });
74
} else {
75
track("open-chat", { project_id, path, how: "chat-button" });
76
actions.open_chat({ path });
77
}
78
},
79
1000,
80
{ leading: true },
81
);
82
const fileUse = useTypedRedux("file_use", "file_use");
83
const isNewChat = useMemo(
84
() =>
85
!!redux.getStore("file_use")?.get_file_info(project_id, path)
86
?.is_unseenchat,
87
[fileUse, project_id, path],
88
);
89
90
if (filename_extension(path) === "sage-chat") {
91
// Special case: do not show side chat for chatrooms
92
return null;
93
}
94
95
return (
96
<Tooltip
97
title={
98
<span>
99
<Icon name="comment" style={{ marginRight: "5px" }} />
100
<FormattedMessage
101
id="chat.chat-indicator.tooltip"
102
defaultMessage={"Hide or Show Document Chat"}
103
/>
104
</span>
105
}
106
placement={"leftTop"}
107
mouseEnterDelay={0.5}
108
>
109
<Button
110
type="text"
111
danger={isNewChat}
112
className={isNewChat ? "smc-chat-notification" : undefined}
113
onClick={toggleChat}
114
style={{ color: chatState ? "orange" : "#333" }}
115
>
116
<Icon name="comment" />
117
<HiddenXS>
118
<span style={{ marginLeft: "5px" }}>
119
{intl.formatMessage(labels.chat)}
120
</span>
121
</HiddenXS>
122
</Button>
123
</Tooltip>
124
);
125
}
126
127