mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
add an option to remove chat from server pro (#20445)
* add option to remove chat from backend * make chat default to enabled * Check chat is enabled in chat context --------- Co-authored-by: mserranom <mserranom@gmail.com> GitOrigin-RevId: 7dda09df4bb74007eb4b1272d4918155b5cddaf6
This commit is contained in:
parent
ce130a8bc5
commit
4a32f49b3d
12 changed files with 92 additions and 39 deletions
|
@ -719,6 +719,7 @@ const _ProjectController = {
|
||||||
isTokenMember,
|
isTokenMember,
|
||||||
isInvitedMember
|
isInvitedMember
|
||||||
),
|
),
|
||||||
|
chatEnabled: Features.hasFeature('chat'),
|
||||||
roMirrorOnClientNoLocalStorage:
|
roMirrorOnClientNoLocalStorage:
|
||||||
Settings.adminOnlyLogin || project.name.startsWith('Debug: '),
|
Settings.adminOnlyLogin || project.name.startsWith('Debug: '),
|
||||||
languages: Settings.languages,
|
languages: Settings.languages,
|
||||||
|
|
|
@ -58,6 +58,8 @@ const Features = {
|
||||||
)
|
)
|
||||||
case 'registration':
|
case 'registration':
|
||||||
return Boolean(Settings.overleaf)
|
return Boolean(Settings.overleaf)
|
||||||
|
case 'chat':
|
||||||
|
return Boolean(Settings.disableChat) === false
|
||||||
case 'github-sync':
|
case 'github-sync':
|
||||||
return Boolean(Settings.enableGithubSync)
|
return Boolean(Settings.enableGithubSync)
|
||||||
case 'git-bridge':
|
case 'git-bridge':
|
||||||
|
|
|
@ -1139,6 +1139,7 @@ async function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||||
SpellingController.unlearn
|
SpellingController.unlearn
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (Features.hasFeature('chat')) {
|
||||||
webRouter.get(
|
webRouter.get(
|
||||||
'/project/:project_id/messages',
|
'/project/:project_id/messages',
|
||||||
AuthorizationMiddleware.blockRestrictedUserFromProject,
|
AuthorizationMiddleware.blockRestrictedUserFromProject,
|
||||||
|
@ -1152,6 +1153,7 @@ async function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||||
RateLimiterMiddleware.rateLimit(rateLimiters.sendChatMessage),
|
RateLimiterMiddleware.rateLimit(rateLimiters.sendChatMessage),
|
||||||
ChatController.sendMessage
|
ChatController.sendMessage
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
webRouter.post(
|
webRouter.post(
|
||||||
'/project/:Project_id/references/indexAll',
|
'/project/:Project_id/references/indexAll',
|
||||||
|
|
|
@ -9,6 +9,7 @@ meta(name="ol-isTokenMember" data-type="boolean" content=isTokenMember)
|
||||||
meta(name="ol-isRestrictedTokenMember" data-type="boolean" content=isRestrictedTokenMember)
|
meta(name="ol-isRestrictedTokenMember" data-type="boolean" content=isRestrictedTokenMember)
|
||||||
meta(name="ol-maxDocLength" data-type="json" content=maxDocLength)
|
meta(name="ol-maxDocLength" data-type="json" content=maxDocLength)
|
||||||
meta(name="ol-wikiEnabled" data-type="boolean" content=settings.proxyLearn)
|
meta(name="ol-wikiEnabled" data-type="boolean" content=settings.proxyLearn)
|
||||||
|
meta(name="ol-chatEnabled" data-type="boolean" content=chatEnabled)
|
||||||
meta(name="ol-gitBridgePublicBaseUrl" content=gitBridgePublicBaseUrl)
|
meta(name="ol-gitBridgePublicBaseUrl" content=gitBridgePublicBaseUrl)
|
||||||
meta(name="ol-gitBridgeEnabled" data-type="boolean" content=gitBridgeEnabled)
|
meta(name="ol-gitBridgeEnabled" data-type="boolean" content=gitBridgeEnabled)
|
||||||
meta(name="ol-compilesUserContentDomain" content=settings.compilesUserContentDomain)
|
meta(name="ol-compilesUserContentDomain" content=settings.compilesUserContentDomain)
|
||||||
|
|
|
@ -407,6 +407,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
disableChat: process.env.OVERLEAF_DISABLE_CHAT === 'true',
|
||||||
enableSubscriptions: false,
|
enableSubscriptions: false,
|
||||||
restrictedCountries: [],
|
restrictedCountries: [],
|
||||||
enableOnboardingEmails: process.env.ENABLE_ONBOARDING_EMAILS === 'true',
|
enableOnboardingEmails: process.env.ENABLE_ONBOARDING_EMAILS === 'true',
|
||||||
|
|
|
@ -17,6 +17,8 @@ import { appendMessage, prependMessages } from '../utils/message-list-appender'
|
||||||
import useBrowserWindow from '../../../shared/hooks/use-browser-window'
|
import useBrowserWindow from '../../../shared/hooks/use-browser-window'
|
||||||
import { useLayoutContext } from '../../../shared/context/layout-context'
|
import { useLayoutContext } from '../../../shared/context/layout-context'
|
||||||
import { useIdeContext } from '@/shared/context/ide-context'
|
import { useIdeContext } from '@/shared/context/ide-context'
|
||||||
|
import getMeta from '@/utils/meta'
|
||||||
|
import { debugConsole } from '@/utils/debugging'
|
||||||
|
|
||||||
const PAGE_SIZE = 50
|
const PAGE_SIZE = 50
|
||||||
|
|
||||||
|
@ -187,6 +189,8 @@ export const ChatContext = createContext<
|
||||||
>(undefined)
|
>(undefined)
|
||||||
|
|
||||||
export const ChatProvider: FC = ({ children }) => {
|
export const ChatProvider: FC = ({ children }) => {
|
||||||
|
const chatEnabled = getMeta('ol-chatEnabled')
|
||||||
|
|
||||||
const clientId = useRef<string>()
|
const clientId = useRef<string>()
|
||||||
if (clientId.current === undefined) {
|
if (clientId.current === undefined) {
|
||||||
clientId.current = chatClientIdGenerator.generate()
|
clientId.current = chatClientIdGenerator.generate()
|
||||||
|
@ -235,6 +239,10 @@ export const ChatProvider: FC = ({ children }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadInitialMessages() {
|
function loadInitialMessages() {
|
||||||
|
if (!chatEnabled) {
|
||||||
|
debugConsole.warn(`chat is disabled, won't load initial messages`)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (state.initialMessagesLoaded) return
|
if (state.initialMessagesLoaded) return
|
||||||
|
|
||||||
dispatch({ type: 'INITIAL_FETCH_MESSAGES' })
|
dispatch({ type: 'INITIAL_FETCH_MESSAGES' })
|
||||||
|
@ -242,11 +250,19 @@ export const ChatProvider: FC = ({ children }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadMoreMessages() {
|
function loadMoreMessages() {
|
||||||
|
if (!chatEnabled) {
|
||||||
|
debugConsole.warn(`chat is disabled, won't load messages`)
|
||||||
|
return
|
||||||
|
}
|
||||||
dispatch({ type: 'FETCH_MESSAGES' })
|
dispatch({ type: 'FETCH_MESSAGES' })
|
||||||
fetchMessages()
|
fetchMessages()
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
|
if (!chatEnabled) {
|
||||||
|
debugConsole.warn(`chat is disabled, won't reset chat`)
|
||||||
|
return
|
||||||
|
}
|
||||||
dispatch({ type: 'CLEAR' })
|
dispatch({ type: 'CLEAR' })
|
||||||
fetchMessages()
|
fetchMessages()
|
||||||
}
|
}
|
||||||
|
@ -256,10 +272,20 @@ export const ChatProvider: FC = ({ children }) => {
|
||||||
loadMoreMessages,
|
loadMoreMessages,
|
||||||
reset,
|
reset,
|
||||||
}
|
}
|
||||||
}, [projectId, state.atEnd, state.initialMessagesLoaded, state.lastTimestamp])
|
}, [
|
||||||
|
chatEnabled,
|
||||||
|
projectId,
|
||||||
|
state.atEnd,
|
||||||
|
state.initialMessagesLoaded,
|
||||||
|
state.lastTimestamp,
|
||||||
|
])
|
||||||
|
|
||||||
const sendMessage = useCallback(
|
const sendMessage = useCallback(
|
||||||
content => {
|
content => {
|
||||||
|
if (!chatEnabled) {
|
||||||
|
debugConsole.warn(`chat is disabled, won't send message`)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (!content) return
|
if (!content) return
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -278,17 +304,21 @@ export const ChatProvider: FC = ({ children }) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
[projectId, user]
|
[chatEnabled, projectId, user]
|
||||||
)
|
)
|
||||||
|
|
||||||
const markMessagesAsRead = useCallback(() => {
|
const markMessagesAsRead = useCallback(() => {
|
||||||
|
if (!chatEnabled) {
|
||||||
|
debugConsole.warn(`chat is disabled, won't mark messages as read`)
|
||||||
|
return
|
||||||
|
}
|
||||||
dispatch({ type: 'MARK_MESSAGES_AS_READ' })
|
dispatch({ type: 'MARK_MESSAGES_AS_READ' })
|
||||||
}, [])
|
}, [chatEnabled])
|
||||||
|
|
||||||
// Handling receiving messages over the socket
|
// Handling receiving messages over the socket
|
||||||
const { socket } = useIdeContext()
|
const { socket } = useIdeContext()
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!socket) return
|
if (!chatEnabled || !socket) return
|
||||||
|
|
||||||
function receivedMessage(message: any) {
|
function receivedMessage(message: any) {
|
||||||
// If the message is from the current client id, then we are receiving the sent message back from the socket.
|
// If the message is from the current client id, then we are receiving the sent message back from the socket.
|
||||||
|
@ -304,7 +334,7 @@ export const ChatProvider: FC = ({ children }) => {
|
||||||
|
|
||||||
socket.removeListener('new-chat-message', receivedMessage)
|
socket.removeListener('new-chat-message', receivedMessage)
|
||||||
}
|
}
|
||||||
}, [socket])
|
}, [chatEnabled, socket])
|
||||||
|
|
||||||
// Handle unread messages
|
// Handle unread messages
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -51,6 +51,8 @@ const ToolbarHeader = React.memo(function ToolbarHeader({
|
||||||
openShareModal,
|
openShareModal,
|
||||||
trackChangesVisible,
|
trackChangesVisible,
|
||||||
}) {
|
}) {
|
||||||
|
const chatEnabled = getMeta('ol-chatEnabled')
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const shouldDisplayPublishButton = hasPublishPermissions && PublishButton
|
const shouldDisplayPublishButton = hasPublishPermissions && PublishButton
|
||||||
|
|
||||||
|
@ -123,7 +125,7 @@ const ToolbarHeader = React.memo(function ToolbarHeader({
|
||||||
|
|
||||||
<LayoutDropdownButton />
|
<LayoutDropdownButton />
|
||||||
|
|
||||||
{chatVisible && (
|
{chatEnabled && chatVisible && (
|
||||||
<ChatToggleButton
|
<ChatToggleButton
|
||||||
chatIsOpen={chatIsOpen}
|
chatIsOpen={chatIsOpen}
|
||||||
onClick={toggleChatOpen}
|
onClick={toggleChatOpen}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { useSidebarPane } from '@/features/ide-react/hooks/use-sidebar-pane'
|
||||||
import { useChatPane } from '@/features/ide-react/hooks/use-chat-pane'
|
import { useChatPane } from '@/features/ide-react/hooks/use-chat-pane'
|
||||||
import { EditorAndPdf } from '@/features/ide-react/components/editor-and-pdf'
|
import { EditorAndPdf } from '@/features/ide-react/components/editor-and-pdf'
|
||||||
import HistoryContainer from '@/features/ide-react/components/history-container'
|
import HistoryContainer from '@/features/ide-react/components/history-container'
|
||||||
|
import getMeta from '@/utils/meta'
|
||||||
|
|
||||||
export const MainLayout: FC = () => {
|
export const MainLayout: FC = () => {
|
||||||
const { view } = useLayoutContext()
|
const { view } = useLayoutContext()
|
||||||
|
@ -38,6 +39,8 @@ export const MainLayout: FC = () => {
|
||||||
handlePaneExpand: handleChatExpand,
|
handlePaneExpand: handleChatExpand,
|
||||||
} = useChatPane()
|
} = useChatPane()
|
||||||
|
|
||||||
|
const chatEnabled = getMeta('ol-chatEnabled')
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -90,6 +93,8 @@ export const MainLayout: FC = () => {
|
||||||
<EditorAndPdf />
|
<EditorAndPdf />
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
||||||
|
{chatEnabled && (
|
||||||
|
<>
|
||||||
<HorizontalResizeHandle
|
<HorizontalResizeHandle
|
||||||
onDoubleClick={toggleChat}
|
onDoubleClick={toggleChat}
|
||||||
resizable={chatIsOpen}
|
resizable={chatIsOpen}
|
||||||
|
@ -111,6 +116,8 @@ export const MainLayout: FC = () => {
|
||||||
>
|
>
|
||||||
<ChatPane />
|
<ChatPane />
|
||||||
</Panel>
|
</Panel>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</PanelGroup>
|
</PanelGroup>
|
||||||
</Panel>
|
</Panel>
|
||||||
</PanelGroup>
|
</PanelGroup>
|
||||||
|
|
|
@ -69,6 +69,7 @@ export interface Meta {
|
||||||
'ol-cannot-link-other-third-party-sso': boolean
|
'ol-cannot-link-other-third-party-sso': boolean
|
||||||
'ol-cannot-reactivate-subscription': boolean
|
'ol-cannot-reactivate-subscription': boolean
|
||||||
'ol-cannot-use-ai': boolean
|
'ol-cannot-use-ai': boolean
|
||||||
|
'ol-chatEnabled': boolean
|
||||||
'ol-countryCode': PricingFormState['country']
|
'ol-countryCode': PricingFormState['country']
|
||||||
'ol-couponCode': PricingFormState['coupon']
|
'ol-couponCode': PricingFormState['coupon']
|
||||||
'ol-createdAt': Date
|
'ol-createdAt': Date
|
||||||
|
|
|
@ -22,6 +22,7 @@ describe('<ChatPane />', function () {
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
window.metaAttributesCache.set('ol-user', user)
|
window.metaAttributesCache.set('ol-user', user)
|
||||||
|
window.metaAttributesCache.set('ol-chatEnabled', true)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
|
|
@ -29,6 +29,7 @@ describe('ChatContext', function () {
|
||||||
stubMathJax()
|
stubMathJax()
|
||||||
|
|
||||||
window.metaAttributesCache.set('ol-user', user)
|
window.metaAttributesCache.set('ol-user', user)
|
||||||
|
window.metaAttributesCache.set('ol-chatEnabled', true)
|
||||||
|
|
||||||
this.stub = sinon.stub(chatClientIdGenerator, 'generate').returns(uuidValue)
|
this.stub = sinon.stub(chatClientIdGenerator, 'generate').returns(uuidValue)
|
||||||
})
|
})
|
||||||
|
|
|
@ -26,6 +26,10 @@ describe('<ToolbarHeader />', function () {
|
||||||
detach: () => {},
|
detach: () => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
window.metaAttributesCache.set('ol-chatEnabled', true)
|
||||||
|
})
|
||||||
|
|
||||||
describe('cobranding logo', function () {
|
describe('cobranding logo', function () {
|
||||||
it('is not displayed by default', function () {
|
it('is not displayed by default', function () {
|
||||||
renderWithEditorContext(<ToolbarHeader {...defaultProps} />)
|
renderWithEditorContext(<ToolbarHeader {...defaultProps} />)
|
||||||
|
|
Loading…
Reference in a new issue