Remove ColorManager (#22974)
GitOrigin-RevId: 32cb6fd599345eaf8e474553da5c6d3080575ee8
This commit is contained in:
@@ -94,7 +94,6 @@ const ChatPane = React.memo(function ChatPane() {
|
||||
{shouldDisplayPlaceholder && <Placeholder />}
|
||||
<MessageList
|
||||
messages={messages}
|
||||
userId={user.id}
|
||||
resetUnreadMessages={markMessagesAsRead}
|
||||
/>
|
||||
</Suspense>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import moment from 'moment'
|
||||
import Message from './message'
|
||||
import { UserId } from '../../../../../types/user'
|
||||
import type { Message as MessageType } from '@/features/chat/context/chat-context'
|
||||
import { useUserContext } from '@/shared/context/user-context'
|
||||
|
||||
const FIVE_MINUTES = 5 * 60 * 1000
|
||||
|
||||
@@ -16,14 +16,11 @@ function formatTimestamp(date: moment.MomentInput) {
|
||||
interface MessageListProps {
|
||||
messages: MessageType[]
|
||||
resetUnreadMessages(...args: unknown[]): unknown
|
||||
userId: UserId | null
|
||||
}
|
||||
|
||||
function MessageList({
|
||||
messages,
|
||||
resetUnreadMessages,
|
||||
userId,
|
||||
}: MessageListProps) {
|
||||
function MessageList({ messages, resetUnreadMessages }: MessageListProps) {
|
||||
const user = useUserContext()
|
||||
|
||||
function shouldRenderDate(messageIndex: number) {
|
||||
if (messageIndex === 0) {
|
||||
return true
|
||||
@@ -61,7 +58,10 @@ function MessageList({
|
||||
</time>
|
||||
</div>
|
||||
)}
|
||||
<Message message={message} userId={userId} />
|
||||
<Message
|
||||
message={message}
|
||||
fromSelf={message.user ? message.user.id === user.id : false}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -1,42 +1,40 @@
|
||||
import { getHueForUserId } from '../../../shared/utils/colors'
|
||||
import { getHueForUserId } from '@/shared/utils/colors'
|
||||
import MessageContent from './message-content'
|
||||
import type { Message as MessageType } from '@/features/chat/context/chat-context'
|
||||
import { User } from '../../../../../types/user'
|
||||
|
||||
interface MessageProps {
|
||||
message: MessageType
|
||||
userId: string | null
|
||||
fromSelf: boolean
|
||||
}
|
||||
|
||||
function Message({ message, userId }: MessageProps) {
|
||||
function hue(user?: User) {
|
||||
return user ? getHueForUserId(user.id, userId) : 0
|
||||
function hue(user?: User) {
|
||||
return user ? getHueForUserId(user.id) : 0
|
||||
}
|
||||
|
||||
function getMessageStyle(user?: User) {
|
||||
return {
|
||||
borderColor: `hsl(${hue(user)}, 85%, 40%)`,
|
||||
backgroundColor: `hsl(${hue(user)}, 85%, 40%`,
|
||||
}
|
||||
}
|
||||
|
||||
function getMessageStyle(user?: User) {
|
||||
return {
|
||||
borderColor: `hsl(${hue(user)}, 85%, 40%)`,
|
||||
backgroundColor: `hsl(${hue(user)}, 85%, 40%`,
|
||||
}
|
||||
function getArrowStyle(user?: User) {
|
||||
return {
|
||||
borderColor: `hsl(${hue(user)}, 85%, 40%)`,
|
||||
}
|
||||
}
|
||||
|
||||
function getArrowStyle(user?: User) {
|
||||
return {
|
||||
borderColor: `hsl(${hue(user)}, 85%, 40%)`,
|
||||
}
|
||||
}
|
||||
|
||||
const isMessageFromSelf = message.user ? message.user.id === userId : false
|
||||
|
||||
function Message({ message, fromSelf }: MessageProps) {
|
||||
return (
|
||||
<div className="message-wrapper">
|
||||
{!isMessageFromSelf && message.user.id && (
|
||||
{!fromSelf && (
|
||||
<div className="name">
|
||||
<span>{message.user.first_name || message.user.email}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="message" style={getMessageStyle(message.user)}>
|
||||
{!isMessageFromSelf && (
|
||||
{!fromSelf && (
|
||||
<div className="arrow" style={getArrowStyle(message.user)} />
|
||||
)}
|
||||
<div className="message-content">
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import {
|
||||
DropdownToggle,
|
||||
} from '@/features/ui/components/bootstrap-5/dropdown-menu'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import { getHueForUserId } from '../../../shared/utils/colors'
|
||||
import { getBackgroundColorForUserId } from '@/shared/utils/colors'
|
||||
import ControlledDropdown from '../../../shared/components/controlled-dropdown'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
@@ -107,7 +107,7 @@ OnlineUsersWidget.propTypes = {
|
||||
}
|
||||
|
||||
function UserIcon({ user, showName, onClick }) {
|
||||
const backgroundColor = `hsl(${getHueForUserId(user.user_id)}, 70%, 50%)`
|
||||
const backgroundColor = getBackgroundColorForUserId(user.user_id)
|
||||
|
||||
function handleOnClick() {
|
||||
onClick?.(user)
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { getUserColor } from '../../utils/history-details'
|
||||
import { LoadedUpdate } from '../../services/types/update'
|
||||
import UserNameWithColoredBadge from './user-name-with-colored-badge'
|
||||
import { getBackgroundColorForUserId } from '@/shared/utils/colors'
|
||||
|
||||
type MetadataUsersListProps = {
|
||||
currentUserId: string
|
||||
@@ -28,7 +28,7 @@ function MetadataUsersList({
|
||||
<li>
|
||||
<span
|
||||
className="history-version-user-badge-color"
|
||||
style={{ backgroundColor: getUserColor() }}
|
||||
style={{ backgroundColor: getBackgroundColorForUserId() }}
|
||||
/>
|
||||
{origin?.kind === 'history-resync' ||
|
||||
origin?.kind === 'history-migration'
|
||||
|
||||
+3
-2
@@ -1,7 +1,8 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { formatUserName, getUserColor } from '../../utils/history-details'
|
||||
import { formatUserName } from '../../utils/history-details'
|
||||
import { User } from '../../services/types/shared'
|
||||
import { Nullable } from '../../../../../../types/utils'
|
||||
import { getBackgroundColorForUserId } from '@/shared/utils/colors'
|
||||
|
||||
type UserNameWithColoredBadgeProps = {
|
||||
currentUserId: string
|
||||
@@ -29,7 +30,7 @@ function UserNameWithColoredBadge({
|
||||
<>
|
||||
<span
|
||||
className="history-version-user-badge-color"
|
||||
style={{ backgroundColor: getUserColor(user) }}
|
||||
style={{ backgroundColor: getBackgroundColorForUserId(user?.id) }}
|
||||
/>
|
||||
<span className="history-version-user-badge-text">{userName}</span>
|
||||
</>
|
||||
|
||||
@@ -17,7 +17,6 @@ import { isFileRenamed } from '../utils/file-diff'
|
||||
import { loadLabels } from '../utils/label'
|
||||
import { autoSelectFile } from '../utils/auto-select-file'
|
||||
import usePersistedState from '../../../shared/hooks/use-persisted-state'
|
||||
import ColorManager from '../../../ide/colors/ColorManager'
|
||||
import moment from 'moment'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import {
|
||||
@@ -28,6 +27,7 @@ import {
|
||||
import { Selection } from '../services/types/selection'
|
||||
import { useErrorHandler } from 'react-error-boundary'
|
||||
import { getUpdateForVersion } from '../utils/history-details'
|
||||
import { getHueForUserId } from '@/shared/utils/colors'
|
||||
|
||||
// Allow testing of infinite scrolling by providing query string parameters to
|
||||
// limit the number of updates returned in a batch and apply a delay
|
||||
@@ -120,7 +120,7 @@ function useHistory() {
|
||||
for (const [index, update] of loadedUpdates.entries()) {
|
||||
for (const user of update.meta.users) {
|
||||
if (user) {
|
||||
user.hue = ColorManager.getHueForUserId(user.id)
|
||||
user.hue = getHueForUserId(user.id)
|
||||
}
|
||||
}
|
||||
if (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import moment from 'moment/moment'
|
||||
import ColorManager from '../../../ide/colors/ColorManager'
|
||||
import { DocDiffChunk, Highlight } from '../services/types/doc'
|
||||
import { TFunction } from 'i18next'
|
||||
import displayNameForUser from './display-name-for-user'
|
||||
import { getHueForUserId } from '@/shared/utils/colors'
|
||||
|
||||
export function highlightsFromDiffResponse(
|
||||
chunks: DocDiffChunk[],
|
||||
@@ -37,7 +37,7 @@ export function highlightsFromDiffResponse(
|
||||
// There doesn't seem to be a convenient way to make this translatable
|
||||
label: t('added_by_on', { name, date }),
|
||||
range,
|
||||
hue: ColorManager.getHueForUserId(user?.id),
|
||||
hue: getHueForUserId(user?.id),
|
||||
})
|
||||
} else if (isDeletion) {
|
||||
highlights.push({
|
||||
@@ -45,7 +45,7 @@ export function highlightsFromDiffResponse(
|
||||
// There doesn't seem to be a convenient way to make this translatable
|
||||
label: t('deleted_by_on', { name, date }),
|
||||
range,
|
||||
hue: ColorManager.getHueForUserId(user?.id),
|
||||
hue: getHueForUserId(user?.id),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import ColorManager from '../../../ide/colors/ColorManager'
|
||||
import { Nullable } from '../../../../../types/utils'
|
||||
import { User } from '../services/types/shared'
|
||||
import { LoadedUpdate, ProjectOp, Version } from '../services/types/update'
|
||||
import { Selection } from '../services/types/selection'
|
||||
|
||||
export const getUserColor = (user?: Nullable<{ id: string }>) => {
|
||||
const hue = ColorManager.getHueForUserId(user?.id) || 100
|
||||
|
||||
return `hsl(${hue}, 70%, 50%)`
|
||||
}
|
||||
|
||||
export const formatUserName = (user: User) => {
|
||||
let name = [user.first_name, user.last_name]
|
||||
.filter(n => n != null)
|
||||
|
||||
@@ -11,7 +11,6 @@ import { ReactScopeValueStore } from '@/features/ide-react/scope-value-store/rea
|
||||
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
|
||||
import { useConnectionContext } from '@/features/ide-react/context/connection-context'
|
||||
import useScopeValue from '@/shared/hooks/use-scope-value'
|
||||
import ColorManager from '@/ide/colors/ColorManager'
|
||||
import { CursorPosition } from '@/features/ide-react/types/cursor-position'
|
||||
import { omit } from 'lodash'
|
||||
import { Doc } from '../../../../../types/doc'
|
||||
@@ -20,6 +19,7 @@ import { findDocEntityById } from '@/features/ide-react/util/find-doc-entity-by-
|
||||
import useSocketListener from '@/features/ide-react/hooks/use-socket-listener'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { IdeEvents } from '@/features/ide-react/create-ide-event-emitter'
|
||||
import { getHueForUserId } from '@/shared/utils/colors'
|
||||
|
||||
type OnlineUser = {
|
||||
id: string
|
||||
@@ -139,7 +139,7 @@ export const OnlineUsersProvider: FC = ({ children }) => {
|
||||
row: user.row,
|
||||
column: user.column,
|
||||
},
|
||||
hue: ColorManager.getHueForUserId(user.user_id),
|
||||
hue: getHueForUserId(user.user_id),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -25,7 +25,6 @@ import {
|
||||
} from '@/features/ide-react/context/editor-manager-context'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { deleteJSON, getJSON, postJSON } from '@/infrastructure/fetch-json'
|
||||
import ColorManager from '@/ide/colors/ColorManager'
|
||||
import RangesTracker from '@overleaf/ranges-tracker'
|
||||
import type * as ReviewPanel from '@/features/source-editor/context/review-panel/types/review-panel-state'
|
||||
import {
|
||||
@@ -66,6 +65,7 @@ import {
|
||||
import { RangesTrackerWithResolvedThreadIds } from '@/features/ide-react/editor/document-container'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { useEditorContext } from '@/shared/context/editor-context'
|
||||
import { getHueForUserId } from '@/shared/utils/colors'
|
||||
|
||||
const dispatchReviewPanelEvent = (type: string, payload?: any) => {
|
||||
window.dispatchEvent(
|
||||
@@ -86,7 +86,7 @@ const formatUser = (user: any): any => {
|
||||
email: null,
|
||||
name: 'Anonymous',
|
||||
isSelf: false,
|
||||
hue: ColorManager.ANONYMOUS_HUE,
|
||||
hue: getHueForUserId(),
|
||||
avatar_text: 'A',
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ const formatUser = (user: any): any => {
|
||||
email: user.email,
|
||||
name,
|
||||
isSelf,
|
||||
hue: ColorManager.getHueForUserId(id),
|
||||
hue: getHueForUserId(id),
|
||||
avatar_text: [user.first_name, user.last_name]
|
||||
.filter(n => n != null)
|
||||
.map(n => n[0])
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Tag } from '../../../../../app/src/Features/Tags/types'
|
||||
import ColorManager from '../../../ide/colors/ColorManager'
|
||||
import { getHueForId } from '@/shared/utils/colors'
|
||||
|
||||
export const MAX_TAG_LENGTH = 50
|
||||
|
||||
@@ -7,5 +7,5 @@ export function getTagColor(tag?: Tag): string | undefined {
|
||||
if (!tag) {
|
||||
return undefined
|
||||
}
|
||||
return tag.color || `hsl(${ColorManager.getHueForTagId(tag._id)}, 70%, 45%)`
|
||||
return tag.color || `hsl(${getHueForId(tag._id)}, 70%, 45%)`
|
||||
}
|
||||
|
||||
+4
-3
@@ -2,7 +2,7 @@ import { memo } from 'react'
|
||||
import { buildName } from '../utils/build-name'
|
||||
import { ReviewPanelUser } from '../../../../../types/review-panel/review-panel'
|
||||
import { ChangesUser } from '../context/changes-users-context'
|
||||
import ColorManager from '@/ide/colors/ColorManager'
|
||||
import { getBackgroundColorForUserId } from '@/shared/utils/colors'
|
||||
|
||||
const ReviewPanelEntryUser = ({
|
||||
user,
|
||||
@@ -10,13 +10,14 @@ const ReviewPanelEntryUser = ({
|
||||
user?: ReviewPanelUser | ChangesUser
|
||||
}) => {
|
||||
const userName = buildName(user)
|
||||
const hue = ColorManager.getHueForUserId(user?.id) || 100
|
||||
|
||||
return (
|
||||
<div className="review-panel-entry-user">
|
||||
<span
|
||||
className="review-panel-entry-user-color-badge"
|
||||
style={{ backgroundColor: `hsl(${hue}, 70%, 50%)` }}
|
||||
style={{
|
||||
backgroundColor: getBackgroundColorForUserId(user?.id),
|
||||
}}
|
||||
/>
|
||||
{userName}
|
||||
</div>
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
max-len,
|
||||
no-return-assign,
|
||||
no-unused-vars,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS101: Remove unnecessary use of Array.from
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
|
||||
// NOTE: this file is being refactored over to frontend/js/shared/utils/colors.js
|
||||
|
||||
import { generateMD5Hash } from './../../shared/utils/md5'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
let ColorManager
|
||||
|
||||
export default ColorManager = {
|
||||
getColorScheme(hue, element) {
|
||||
if (this.isDarkTheme(element)) {
|
||||
return {
|
||||
cursor: `hsl(${hue}, 70%, 50%)`,
|
||||
labelBackgroundColor: `hsl(${hue}, 70%, 50%)`,
|
||||
highlightBackgroundColor: `hsl(${hue}, 100%, 28%);`,
|
||||
strikeThroughBackgroundColor: `hsl(${hue}, 100%, 20%);`,
|
||||
strikeThroughForegroundColor: `hsl(${hue}, 100%, 60%);`,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
cursor: `hsl(${hue}, 70%, 50%)`,
|
||||
labelBackgroundColor: `hsl(${hue}, 70%, 50%)`,
|
||||
highlightBackgroundColor: `hsl(${hue}, 70%, 85%);`,
|
||||
strikeThroughBackgroundColor: `hsl(${hue}, 70%, 95%);`,
|
||||
strikeThroughForegroundColor: `hsl(${hue}, 70%, 40%);`,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
isDarkTheme(element) {
|
||||
const rgb = element.find('.ace_editor').css('background-color')
|
||||
let [m, r, g, b] = Array.from(
|
||||
rgb.match(/rgb\(([0-9]+), ([0-9]+), ([0-9]+)\)/)
|
||||
)
|
||||
r = parseInt(r, 10)
|
||||
g = parseInt(g, 10)
|
||||
b = parseInt(b, 10)
|
||||
return r + g + b < 3 * 128
|
||||
},
|
||||
|
||||
ANONYMOUS_HUE: 100,
|
||||
OWN_HUE: 200, // We will always appear as this color to ourselves
|
||||
OWN_HUE_BLOCKED_SIZE: 20, // no other user should havea HUE in this range
|
||||
TOTAL_HUES: 360, // actually 361, but 360 for legacy reasons
|
||||
getHueForUserId(user_id) {
|
||||
if (user_id == null || user_id === 'anonymous-user') {
|
||||
return this.ANONYMOUS_HUE
|
||||
}
|
||||
|
||||
if (getMeta('ol-user').id === user_id) {
|
||||
return this.OWN_HUE
|
||||
}
|
||||
|
||||
let hue = this.getHueForId(user_id)
|
||||
|
||||
// if `hue` is within `OWN_HUE_BLOCKED_SIZE` degrees of the personal hue
|
||||
// (`OWN_HUE`), shift `hue` to the end of available hues by adding
|
||||
if (
|
||||
hue > this.OWN_HUE - this.OWN_HUE_BLOCKED_SIZE &&
|
||||
hue < this.OWN_HUE + this.OWN_HUE_BLOCKED_SIZE
|
||||
) {
|
||||
hue = hue - this.OWN_HUE // `hue` now at 0 +/- `OWN_HUE_BLOCKED_SIZE`
|
||||
hue = hue + this.TOTAL_HUES - this.OWN_HUE_BLOCKED_SIZE
|
||||
}
|
||||
|
||||
return hue
|
||||
},
|
||||
|
||||
getHueForTagId(tag_id) {
|
||||
return this.getHueForId(tag_id)
|
||||
},
|
||||
|
||||
getHueForId(id) {
|
||||
const hash = generateMD5Hash(id)
|
||||
const hue =
|
||||
parseInt(hash.toString().slice(0, 8), 16) %
|
||||
(this.TOTAL_HUES - this.OWN_HUE_BLOCKED_SIZE * 2)
|
||||
return hue
|
||||
},
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
import { generateMD5Hash } from './md5'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
const ANONYMOUS_HUE = 100
|
||||
const OWN_HUE = 200 // We will always appear as this color to ourselves
|
||||
const OWN_HUE_BLOCKED_SIZE = 20 // no other user should have a HUE in this range
|
||||
const TOTAL_HUES = 360 // actually 361, but 360 for legacy reasons
|
||||
|
||||
export function getHueForUserId(userId: string, currentUserId: string | null) {
|
||||
export function getHueForUserId(userId?: string): number {
|
||||
if (userId == null || userId === 'anonymous-user') {
|
||||
return ANONYMOUS_HUE
|
||||
}
|
||||
|
||||
if (currentUserId === userId) {
|
||||
if (getMeta('ol-user_id') === userId) {
|
||||
return OWN_HUE
|
||||
}
|
||||
|
||||
@@ -29,10 +30,23 @@ export function getHueForUserId(userId: string, currentUserId: string | null) {
|
||||
return hue
|
||||
}
|
||||
|
||||
function getHueForId(id: string) {
|
||||
export function getBackgroundColorForUserId(userId?: string) {
|
||||
return `hsl(${getHueForUserId(userId)}, 70%, 50%)`
|
||||
}
|
||||
|
||||
const cachedHues = new Map()
|
||||
|
||||
export function getHueForId(id: string) {
|
||||
if (cachedHues.has(id)) {
|
||||
return cachedHues.get(id)
|
||||
}
|
||||
|
||||
const hash = generateMD5Hash(id)
|
||||
|
||||
const hue =
|
||||
parseInt(hash.toString().slice(0, 8), 16) %
|
||||
(TOTAL_HUES - OWN_HUE_BLOCKED_SIZE * 2)
|
||||
parseInt(hash.slice(0, 8), 16) % (TOTAL_HUES - OWN_HUE_BLOCKED_SIZE * 2)
|
||||
|
||||
cachedHues.set(id, hue)
|
||||
|
||||
return hue
|
||||
}
|
||||
|
||||
+49
-10
@@ -8,9 +8,9 @@
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
|
||||
export function generateMD5Hash(inputString) {
|
||||
export function generateMD5Hash(inputString: string): string {
|
||||
const hc = '0123456789abcdef'
|
||||
function rh(n) {
|
||||
function rh(n: number) {
|
||||
let j
|
||||
let s = ''
|
||||
for (j = 0; j <= 3; j++)
|
||||
@@ -18,30 +18,69 @@ export function generateMD5Hash(inputString) {
|
||||
hc.charAt((n >> (j * 8 + 4)) & 0x0f) + hc.charAt((n >> (j * 8)) & 0x0f)
|
||||
return s
|
||||
}
|
||||
function ad(x, y) {
|
||||
function ad(x: number, y: number) {
|
||||
const l = (x & 0xffff) + (y & 0xffff)
|
||||
const m = (x >> 16) + (y >> 16) + (l >> 16)
|
||||
return (m << 16) | (l & 0xffff)
|
||||
}
|
||||
function rl(n, c) {
|
||||
function rl(n: number, c: number) {
|
||||
return (n << c) | (n >>> (32 - c))
|
||||
}
|
||||
function cm(q, a, b, x, s, t) {
|
||||
function cm(
|
||||
q: number,
|
||||
a: number,
|
||||
b: number,
|
||||
x: number,
|
||||
s: number,
|
||||
t: number
|
||||
) {
|
||||
return ad(rl(ad(ad(a, q), ad(x, t)), s), b)
|
||||
}
|
||||
function ff(a, b, c, d, x, s, t) {
|
||||
function ff(
|
||||
a: number,
|
||||
b: number,
|
||||
c: number,
|
||||
d: number,
|
||||
x: number,
|
||||
s: number,
|
||||
t: number
|
||||
) {
|
||||
return cm((b & c) | (~b & d), a, b, x, s, t)
|
||||
}
|
||||
function gg(a, b, c, d, x, s, t) {
|
||||
function gg(
|
||||
a: number,
|
||||
b: number,
|
||||
c: number,
|
||||
d: number,
|
||||
x: number,
|
||||
s: number,
|
||||
t: number
|
||||
) {
|
||||
return cm((b & d) | (c & ~d), a, b, x, s, t)
|
||||
}
|
||||
function hh(a, b, c, d, x, s, t) {
|
||||
function hh(
|
||||
a: number,
|
||||
b: number,
|
||||
c: number,
|
||||
d: number,
|
||||
x: number,
|
||||
s: number,
|
||||
t: number
|
||||
) {
|
||||
return cm(b ^ c ^ d, a, b, x, s, t)
|
||||
}
|
||||
function ii(a, b, c, d, x, s, t) {
|
||||
function ii(
|
||||
a: number,
|
||||
b: number,
|
||||
c: number,
|
||||
d: number,
|
||||
x: number,
|
||||
s: number,
|
||||
t: number
|
||||
) {
|
||||
return cm(c ^ (b | ~d), a, b, x, s, t)
|
||||
}
|
||||
function sb(x) {
|
||||
function sb(x: string) {
|
||||
let i
|
||||
const nblk = ((x.length + 8) >> 6) + 1
|
||||
const blks = new Array(nblk * 16)
|
||||
@@ -3,6 +3,7 @@ import useFetchMock from './hooks/use-fetch-mock'
|
||||
import { generateMessages } from './fixtures/chat-messages'
|
||||
import { ScopeDecorator } from './decorators/scope'
|
||||
import { bsVersionDecorator } from '../../.storybook/utils/with-bootstrap-switcher'
|
||||
import { UserProvider } from '@/shared/context/user-context'
|
||||
|
||||
export const Conversation = args => {
|
||||
useFetchMock(fetchMock => {
|
||||
@@ -48,5 +49,12 @@ export default {
|
||||
args: {
|
||||
resetUnreadMessages: () => {},
|
||||
},
|
||||
decorators: [ScopeDecorator],
|
||||
decorators: [
|
||||
ScopeDecorator,
|
||||
Story => (
|
||||
<UserProvider>
|
||||
<Story />
|
||||
</UserProvider>
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { screen, render, fireEvent } from '@testing-library/react'
|
||||
|
||||
import MessageList from '../../../../../frontend/js/features/chat/components/message-list'
|
||||
import { stubMathJax, tearDownMathJaxStubs } from './stubs'
|
||||
import { UserProvider } from '@/shared/context/user-context'
|
||||
|
||||
describe('<MessageList />', function () {
|
||||
const currentUser = {
|
||||
@@ -37,13 +38,25 @@ describe('<MessageList />', function () {
|
||||
tearDownMathJaxStubs()
|
||||
})
|
||||
|
||||
let olUser
|
||||
beforeEach(function () {
|
||||
olUser = window.metaAttributesCache.get('ol-user')
|
||||
window.metaAttributesCache.set('ol-user', currentUser)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache.set('ol-user', olUser)
|
||||
})
|
||||
|
||||
it('renders multiple messages', function () {
|
||||
render(
|
||||
<MessageList
|
||||
userId={currentUser.id}
|
||||
messages={createMessages()}
|
||||
resetUnreadMessages={() => {}}
|
||||
/>
|
||||
<UserProvider>
|
||||
<MessageList
|
||||
userId={currentUser.id}
|
||||
messages={createMessages()}
|
||||
resetUnreadMessages={() => {}}
|
||||
/>
|
||||
</UserProvider>
|
||||
)
|
||||
|
||||
screen.getByText('a message')
|
||||
@@ -56,11 +69,13 @@ describe('<MessageList />', function () {
|
||||
msgs[1].timestamp = new Date(2019, 6, 3, 4, 27).getTime()
|
||||
|
||||
render(
|
||||
<MessageList
|
||||
userId={currentUser.id}
|
||||
messages={msgs}
|
||||
resetUnreadMessages={() => {}}
|
||||
/>
|
||||
<UserProvider>
|
||||
<MessageList
|
||||
userId={currentUser.id}
|
||||
messages={msgs}
|
||||
resetUnreadMessages={() => {}}
|
||||
/>
|
||||
</UserProvider>
|
||||
)
|
||||
|
||||
screen.getByText('4:23 am Wed, 3rd Jul 19')
|
||||
@@ -73,11 +88,13 @@ describe('<MessageList />', function () {
|
||||
msgs[1].timestamp = new Date(2019, 6, 3, 4, 31).getTime()
|
||||
|
||||
render(
|
||||
<MessageList
|
||||
userId={currentUser.id}
|
||||
messages={msgs}
|
||||
resetUnreadMessages={() => {}}
|
||||
/>
|
||||
<UserProvider>
|
||||
<MessageList
|
||||
userId={currentUser.id}
|
||||
messages={msgs}
|
||||
resetUnreadMessages={() => {}}
|
||||
/>
|
||||
</UserProvider>
|
||||
)
|
||||
|
||||
screen.getByText('4:23 am Wed, 3rd Jul 19')
|
||||
@@ -87,11 +104,13 @@ describe('<MessageList />', function () {
|
||||
it('resets the number of unread messages after clicking on the input', function () {
|
||||
const resetUnreadMessages = sinon.stub()
|
||||
render(
|
||||
<MessageList
|
||||
userId={currentUser.id}
|
||||
messages={createMessages()}
|
||||
resetUnreadMessages={resetUnreadMessages}
|
||||
/>
|
||||
<UserProvider>
|
||||
<MessageList
|
||||
userId={currentUser.id}
|
||||
messages={createMessages()}
|
||||
resetUnreadMessages={resetUnreadMessages}
|
||||
/>
|
||||
</UserProvider>
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('list'))
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('<Message />', function () {
|
||||
user: currentUser,
|
||||
}
|
||||
|
||||
render(<Message userId={currentUser.id} message={message} />)
|
||||
render(<Message message={message} fromSelf />)
|
||||
|
||||
screen.getByText('a message')
|
||||
})
|
||||
@@ -37,7 +37,7 @@ describe('<Message />', function () {
|
||||
user: currentUser,
|
||||
}
|
||||
|
||||
render(<Message userId={currentUser.id} message={message} />)
|
||||
render(<Message message={message} fromSelf />)
|
||||
|
||||
screen.getByText('a message')
|
||||
screen.getByText('another message')
|
||||
@@ -51,7 +51,7 @@ describe('<Message />', function () {
|
||||
user: currentUser,
|
||||
}
|
||||
|
||||
render(<Message userId={currentUser.id} message={message} />)
|
||||
render(<Message message={message} fromSelf />)
|
||||
|
||||
screen.getByRole('link', { name: 'https://overleaf.com' })
|
||||
})
|
||||
@@ -63,7 +63,7 @@ describe('<Message />', function () {
|
||||
}
|
||||
|
||||
it('does not render the user name nor the email', function () {
|
||||
render(<Message userId={currentUser.id} message={message} />)
|
||||
render(<Message message={message} fromSelf />)
|
||||
|
||||
expect(screen.queryByText(currentUser.first_name)).to.not.exist
|
||||
expect(screen.queryByText(currentUser.email)).to.not.exist
|
||||
@@ -82,7 +82,7 @@ describe('<Message />', function () {
|
||||
}
|
||||
|
||||
it('should render the other user name', function () {
|
||||
render(<Message userId={currentUser.id} message={message} />)
|
||||
render(<Message message={message} />)
|
||||
|
||||
screen.getByText(otherUser.first_name)
|
||||
})
|
||||
@@ -96,7 +96,7 @@ describe('<Message />', function () {
|
||||
},
|
||||
}
|
||||
|
||||
render(<Message userId={currentUser.id} message={msg} />)
|
||||
render(<Message message={msg} />)
|
||||
|
||||
expect(screen.queryByText(otherUser.first_name)).to.not.exist
|
||||
screen.getByText(msg.user.email)
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ProjectListProvider } from '../../../../../frontend/js/features/project
|
||||
import { Project } from '../../../../../types/project/dashboard/api'
|
||||
import { projectsData } from '../fixtures/projects-data'
|
||||
import { SplitTestProvider } from '@/shared/context/split-test-context'
|
||||
import { UserProvider } from '@/shared/context/user-context'
|
||||
|
||||
type Options = {
|
||||
projects?: Project[]
|
||||
@@ -31,16 +32,24 @@ export function renderWithProjectListContext(
|
||||
body: [],
|
||||
})
|
||||
|
||||
window.metaAttributesCache.set('ol-user', {
|
||||
id: 'fake_user',
|
||||
first_name: 'fake_user_first_name',
|
||||
email: 'fake@example.com',
|
||||
})
|
||||
|
||||
const ProjectListProviderWrapper = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) => (
|
||||
<ProjectListProvider>
|
||||
<SplitTestProvider>
|
||||
<ColorPickerProvider>{children}</ColorPickerProvider>
|
||||
</SplitTestProvider>
|
||||
</ProjectListProvider>
|
||||
<UserProvider>
|
||||
<ProjectListProvider>
|
||||
<SplitTestProvider>
|
||||
<ColorPickerProvider>{children}</ColorPickerProvider>
|
||||
</SplitTestProvider>
|
||||
</ProjectListProvider>
|
||||
</UserProvider>
|
||||
)
|
||||
|
||||
return render(component, {
|
||||
|
||||
@@ -3,11 +3,15 @@ import { expect } from 'chai'
|
||||
import { getHueForUserId } from '@/shared/utils/colors'
|
||||
|
||||
describe('colors', function () {
|
||||
const currentUser = '5bf7dab7a18b0b7a1cf6738c'
|
||||
const currentUserId = '5bf7dab7a18b0b7a1cf6738c'
|
||||
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set('ol-user_id', currentUserId)
|
||||
})
|
||||
|
||||
describe('getHueForUserId', function () {
|
||||
it('returns the OWN_HUE for the current user', function () {
|
||||
expect(getHueForUserId(currentUser, currentUser)).to.equal(200)
|
||||
expect(getHueForUserId(currentUserId)).to.equal(200)
|
||||
})
|
||||
|
||||
it('returns the ANONYMOUS_HUE for an anonymous user', function () {
|
||||
@@ -16,18 +20,16 @@ describe('colors', function () {
|
||||
})
|
||||
|
||||
it('generates a hue based on user id', function () {
|
||||
expect(getHueForUserId('59ad79f46337430b3d37cb9e', currentUser)).to.equal(
|
||||
146
|
||||
)
|
||||
expect(
|
||||
getHueForUserId('59ad79f46337430b3d37cb9e', currentUserId)
|
||||
).to.equal(146)
|
||||
})
|
||||
|
||||
it('shifts the hue away from the OWN_HUE if it is within a threshold', function () {
|
||||
// Ordinarily, this user id would generate a hue of 183. However, this is
|
||||
// visually "too close" to the OWN_HUE, meaning that it could be
|
||||
// misinterpreted. Therefore we shift it away
|
||||
expect(getHueForUserId('20ad79f46337430b3d37cb9f', currentUser)).to.equal(
|
||||
323
|
||||
)
|
||||
expect(getHueForUserId('20ad79f46337430b3d37cb9f')).to.equal(323)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect } from 'chai'
|
||||
|
||||
import { generateMD5Hash } from '../../../../frontend/js/shared/utils/md5'
|
||||
import { generateMD5Hash } from '@/shared/utils/md5'
|
||||
|
||||
describe('md5', function () {
|
||||
describe('generateSHA1Hash', function () {
|
||||
|
||||
Reference in New Issue
Block a user