@weavy/uikit-react 11.2.0 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +1 -1
- package/changelog.md +15 -0
- package/dist/cjs/index.js +6 -6
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/Image.d.ts +2 -0
- package/dist/cjs/types/components/PdfViewer.d.ts +6 -0
- package/dist/cjs/types/components/Preview.d.ts +58 -0
- package/dist/cjs/types/types/types.d.ts +1 -0
- package/dist/cjs/types/utils/fileUtilities.d.ts +16 -1
- package/dist/css/weavy-chat.css +2684 -0
- package/dist/css/weavy-messenger.css +3039 -0
- package/dist/css/weavy.css +3039 -0
- package/dist/esm/index.js +6 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/Image.d.ts +2 -0
- package/dist/esm/types/components/PdfViewer.d.ts +6 -0
- package/dist/esm/types/components/Preview.d.ts +58 -0
- package/dist/esm/types/types/types.d.ts +1 -0
- package/dist/esm/types/utils/fileUtilities.d.ts +16 -1
- package/package.json +14 -4
- package/rollup.config.js +0 -2
- package/src/components/Attachment.tsx +5 -6
- package/src/components/Avatar.tsx +2 -3
- package/src/components/Chat.tsx +3 -4
- package/src/components/Conversation.tsx +20 -29
- package/src/components/ConversationBadge.tsx +1 -2
- package/src/components/ConversationForm.tsx +11 -18
- package/src/components/ConversationList.tsx +4 -5
- package/src/components/ConversationListItem.tsx +11 -13
- package/src/components/FileBrowser.tsx +1 -2
- package/src/components/Image.tsx +39 -7
- package/src/components/MeetingCard.tsx +7 -8
- package/src/components/Message.tsx +12 -13
- package/src/components/Messages.tsx +6 -7
- package/src/components/Messenger.tsx +3 -4
- package/src/components/NewConversation.tsx +5 -7
- package/src/components/PdfViewer.tsx +271 -0
- package/src/components/Presence.tsx +2 -2
- package/src/components/Preview.tsx +294 -0
- package/src/components/Reactions.tsx +6 -7
- package/src/components/SearchUsers.tsx +17 -16
- package/src/components/SeenBy.tsx +1 -2
- package/src/contexts/PreviewContext.tsx +4 -6
- package/src/hooks/useConversation.ts +0 -1
- package/src/hooks/usePresence.ts +4 -5
- package/src/hooks/useReactions.ts +0 -1
- package/src/scss/theme/_alert.scss +73 -0
- package/src/scss/theme/_appbar.scss +112 -0
- package/src/scss/theme/_attachments.scss +74 -0
- package/src/scss/theme/_avatar.scss +54 -0
- package/src/scss/theme/_badge.scss +47 -0
- package/src/scss/theme/_buttons.scss +96 -0
- package/src/scss/theme/_card.scss +7 -0
- package/src/scss/theme/_checkbox.scss +56 -0
- package/src/scss/theme/_cm-editor.scss +42 -0
- package/src/scss/theme/_code.scss +115 -0
- package/src/scss/theme/_colors.scss +520 -0
- package/src/scss/theme/_config.scss +6 -0
- package/src/scss/theme/_content.scss +15 -0
- package/src/scss/theme/_conversations.scss +91 -0
- package/src/scss/theme/_dropdown.scss +86 -0
- package/src/scss/theme/_emoji.scss +5 -0
- package/src/scss/theme/_filebrowser.scss +26 -0
- package/src/scss/theme/_files.scss +140 -0
- package/src/scss/theme/_icons.scss +62 -0
- package/src/scss/theme/_image-grid.scss +63 -0
- package/src/scss/theme/_inputs.scss +28 -0
- package/src/scss/theme/_message-editor.scss +90 -0
- package/src/scss/theme/_messages.scss +238 -0
- package/src/scss/theme/_nav.scss +52 -0
- package/src/scss/theme/_overlays.scss +157 -0
- package/src/scss/theme/_pager.scss +19 -0
- package/src/scss/theme/_palette.scss +165 -0
- package/src/scss/theme/_pane.scss +16 -0
- package/src/scss/theme/_panels.scss +137 -0
- package/src/scss/theme/_picker-list.scss +37 -0
- package/src/scss/theme/_preview-embed.scss +38 -0
- package/src/scss/theme/_preview-html.scss +7 -0
- package/src/scss/theme/_preview-icon.scss +41 -0
- package/src/scss/theme/_preview-image.scss +86 -0
- package/src/scss/theme/_preview-media.scss +28 -0
- package/src/scss/theme/_preview-pdf.scss +838 -0
- package/src/scss/theme/_preview-text.scss +5 -0
- package/src/scss/theme/_preview.scss +105 -0
- package/src/scss/theme/_reactions.scss +58 -0
- package/src/scss/theme/_reboot.scss +41 -0
- package/src/scss/theme/_root.scss +2 -0
- package/src/scss/theme/_scroll.scss +55 -0
- package/src/scss/theme/_search.scss +68 -0
- package/src/scss/theme/_spinner.scss +63 -0
- package/src/scss/theme/_tables.scss +53 -0
- package/src/scss/theme/_toasts.scss +47 -0
- package/src/scss/theme/_turbo.scss +17 -0
- package/src/scss/theme/_typing.scss +26 -0
- package/src/scss/theme/_variables.scss +139 -0
- package/src/scss/theme/bootstrap/_accordion.scss +146 -0
- package/src/scss/theme/bootstrap/_alert.scss +71 -0
- package/src/scss/theme/bootstrap/_badge.scss +38 -0
- package/src/scss/theme/bootstrap/_breadcrumb.scss +40 -0
- package/src/scss/theme/bootstrap/_button-group.scss +142 -0
- package/src/scss/theme/bootstrap/_buttons.scss +186 -0
- package/src/scss/theme/bootstrap/_card.scss +234 -0
- package/src/scss/theme/bootstrap/_carousel.scss +229 -0
- package/src/scss/theme/bootstrap/_close.scss +40 -0
- package/src/scss/theme/bootstrap/_containers.scss +41 -0
- package/src/scss/theme/bootstrap/_dropdown.scss +248 -0
- package/src/scss/theme/bootstrap/_forms.scss +9 -0
- package/src/scss/theme/bootstrap/_functions.scss +302 -0
- package/src/scss/theme/bootstrap/_grid.scss +33 -0
- package/src/scss/theme/bootstrap/_helpers.scss +10 -0
- package/src/scss/theme/bootstrap/_images.scss +42 -0
- package/src/scss/theme/bootstrap/_list-group.scss +191 -0
- package/src/scss/theme/bootstrap/_maps.scss +54 -0
- package/src/scss/theme/bootstrap/_mixins.scss +43 -0
- package/src/scss/theme/bootstrap/_modal.scss +237 -0
- package/src/scss/theme/bootstrap/_nav.scss +172 -0
- package/src/scss/theme/bootstrap/_navbar.scss +276 -0
- package/src/scss/theme/bootstrap/_offcanvas.scss +143 -0
- package/src/scss/theme/bootstrap/_pagination.scss +109 -0
- package/src/scss/theme/bootstrap/_placeholders.scss +51 -0
- package/src/scss/theme/bootstrap/_popover.scss +196 -0
- package/src/scss/theme/bootstrap/_progress.scss +59 -0
- package/src/scss/theme/bootstrap/_reboot.scss +610 -0
- package/src/scss/theme/bootstrap/_root.scss +73 -0
- package/src/scss/theme/bootstrap/_spinners.scss +85 -0
- package/src/scss/theme/bootstrap/_tables.scss +164 -0
- package/src/scss/theme/bootstrap/_toasts.scss +70 -0
- package/src/scss/theme/bootstrap/_tooltip.scss +120 -0
- package/src/scss/theme/bootstrap/_transitions.scss +27 -0
- package/src/scss/theme/bootstrap/_type.scss +106 -0
- package/src/scss/theme/bootstrap/_utilities.scss +647 -0
- package/src/scss/theme/bootstrap/_variables.scss +1633 -0
- package/src/scss/theme/bootstrap/forms/_floating-labels.scss +74 -0
- package/src/scss/theme/bootstrap/forms/_form-check.scss +175 -0
- package/src/scss/theme/bootstrap/forms/_form-control.scss +194 -0
- package/src/scss/theme/bootstrap/forms/_form-range.scss +91 -0
- package/src/scss/theme/bootstrap/forms/_form-select.scss +71 -0
- package/src/scss/theme/bootstrap/forms/_form-text.scss +11 -0
- package/src/scss/theme/bootstrap/forms/_input-group.scss +129 -0
- package/src/scss/theme/bootstrap/forms/_labels.scss +36 -0
- package/src/scss/theme/bootstrap/forms/_validation.scss +12 -0
- package/src/scss/theme/bootstrap/helpers/_clearfix.scss +3 -0
- package/src/scss/theme/bootstrap/helpers/_color-bg.scss +10 -0
- package/src/scss/theme/bootstrap/helpers/_colored-links.scss +12 -0
- package/src/scss/theme/bootstrap/helpers/_position.scss +36 -0
- package/src/scss/theme/bootstrap/helpers/_ratio.scss +26 -0
- package/src/scss/theme/bootstrap/helpers/_stacks.scss +15 -0
- package/src/scss/theme/bootstrap/helpers/_stretched-link.scss +15 -0
- package/src/scss/theme/bootstrap/helpers/_text-truncation.scss +7 -0
- package/src/scss/theme/bootstrap/helpers/_visually-hidden.scss +8 -0
- package/src/scss/theme/bootstrap/helpers/_vr.scss +8 -0
- package/src/scss/theme/bootstrap/mixins/_alert.scss +15 -0
- package/src/scss/theme/bootstrap/mixins/_backdrop.scss +14 -0
- package/src/scss/theme/bootstrap/mixins/_banner.scss +9 -0
- package/src/scss/theme/bootstrap/mixins/_border-radius.scss +78 -0
- package/src/scss/theme/bootstrap/mixins/_box-shadow.scss +18 -0
- package/src/scss/theme/bootstrap/mixins/_breakpoints.scss +127 -0
- package/src/scss/theme/bootstrap/mixins/_buttons.scss +70 -0
- package/src/scss/theme/bootstrap/mixins/_caret.scss +64 -0
- package/src/scss/theme/bootstrap/mixins/_clearfix.scss +9 -0
- package/src/scss/theme/bootstrap/mixins/_color-scheme.scss +7 -0
- package/src/scss/theme/bootstrap/mixins/_container.scss +11 -0
- package/src/scss/theme/bootstrap/mixins/_deprecate.scss +10 -0
- package/src/scss/theme/bootstrap/mixins/_forms.scss +152 -0
- package/src/scss/theme/bootstrap/mixins/_gradients.scss +47 -0
- package/src/scss/theme/bootstrap/mixins/_grid.scss +151 -0
- package/src/scss/theme/bootstrap/mixins/_image.scss +16 -0
- package/src/scss/theme/bootstrap/mixins/_list-group.scss +24 -0
- package/src/scss/theme/bootstrap/mixins/_lists.scss +7 -0
- package/src/scss/theme/bootstrap/mixins/_pagination.scss +10 -0
- package/src/scss/theme/bootstrap/mixins/_reset-text.scss +17 -0
- package/src/scss/theme/bootstrap/mixins/_resize.scss +6 -0
- package/src/scss/theme/bootstrap/mixins/_table-variants.scss +24 -0
- package/src/scss/theme/bootstrap/mixins/_text-truncate.scss +8 -0
- package/src/scss/theme/bootstrap/mixins/_transition.scss +26 -0
- package/src/scss/theme/bootstrap/mixins/_utilities.scss +97 -0
- package/src/scss/theme/bootstrap/mixins/_visually-hidden.scss +29 -0
- package/src/scss/theme/bootstrap/utilities/_api.scss +47 -0
- package/src/scss/theme/bootstrap/vendor/_rfs.scss +354 -0
- package/src/scss/theme/bs/_badge.scss +20 -0
- package/src/scss/theme/bs/_buttons.scss +185 -0
- package/src/scss/theme/bs/_dropdown.scss +86 -0
- package/src/scss/theme/bs/_forms.scss +161 -0
- package/src/scss/theme/bs/_list-group.scss +73 -0
- package/src/scss/theme/bs/_tables.scss +46 -0
- package/src/scss/theme/fonts/_fontmapping-roboto.scss +129 -0
- package/src/scss/theme/fonts/_fontmapping-segoe-ui.scss +127 -0
- package/src/scss/theme/fonts/_index.scss +2 -0
- package/src/scss/theme/mixins/_backdrop.scss +13 -0
- package/src/scss/theme/mixins/_palette.scss +165 -0
- package/src/scss/theme/mixins/_position.scss +33 -0
- package/src/scss/theme/mixins/_scrollbar.scss +110 -0
- package/src/scss/weavy-chat.scss +31 -0
- package/src/scss/weavy-messenger.scss +60 -0
- package/src/scss/weavy.scss +2 -0
- package/src/types/types.ts +2 -0
- package/src/ui/Button.tsx +3 -4
- package/src/ui/Dropdown.tsx +4 -5
- package/src/ui/Icon.tsx +75 -39
- package/src/ui/Overlay.tsx +2 -3
- package/src/utils/fileUtilities.ts +280 -72
- package/src/utils/scrollbarDetection.js +5 -7
- package/dist/cjs/types/utils/styles.d.ts +0 -17
- package/dist/esm/types/utils/styles.d.ts +0 -17
- package/src/utils/styles.ts +0 -57
package/src/components/Image.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { prefix as wy } from "../utils/styles";
|
|
1
|
+
import React, { useCallback } from "react";
|
|
3
2
|
|
|
4
3
|
type ImageProps = {
|
|
5
4
|
src: string,
|
|
@@ -10,6 +9,33 @@ type ImageProps = {
|
|
|
10
9
|
onClick: (e: any) => void
|
|
11
10
|
}
|
|
12
11
|
|
|
12
|
+
export function checkImageLoad(img: HTMLImageElement) {
|
|
13
|
+
var isLoaded = img.complete && img.naturalHeight !== 0;
|
|
14
|
+
if (isLoaded) {
|
|
15
|
+
if (!img.classList.contains("wy-loading")) {
|
|
16
|
+
console.debug("image is instantly loaded")
|
|
17
|
+
img.classList.add("wy-loading", "wy-loaded");
|
|
18
|
+
} else {
|
|
19
|
+
img.decode().then(() => {
|
|
20
|
+
console.debug("image is loaded after delay")
|
|
21
|
+
img.classList.add("wy-loaded");
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
} else {
|
|
27
|
+
console.debug("image is loading")
|
|
28
|
+
img.classList.add("wy-loading");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function imageLoaded(event: any) {
|
|
33
|
+
var img = event.target;
|
|
34
|
+
if (img.tagName === 'IMG' && img.classList.contains("wy-loading") && !img.classList.contains("wy-loaded")) {
|
|
35
|
+
console.debug("load event"); img.classList.add("wy-loaded")
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
13
39
|
export const Image = ({src, previewSrc, width, height, more, onClick}: ImageProps) => {
|
|
14
40
|
let ratio = width / height;
|
|
15
41
|
let baseSize = 64;
|
|
@@ -20,17 +46,23 @@ export const Image = ({src, previewSrc, width, height, more, onClick}: ImageProp
|
|
|
20
46
|
let intrinsicWidth = width + "px"
|
|
21
47
|
let maxWidth = (maxScale * width) + "px";
|
|
22
48
|
|
|
49
|
+
const imageRef = useCallback((element: HTMLImageElement) => {
|
|
50
|
+
if (element) {
|
|
51
|
+
checkImageLoad(element);
|
|
52
|
+
}
|
|
53
|
+
}, [])
|
|
54
|
+
|
|
23
55
|
return (
|
|
24
|
-
<a href={src} className=
|
|
56
|
+
<a href={src} className="wy-image" onClick={(e) => onClick(e)} style={{
|
|
25
57
|
flexBasis: flexBasis,
|
|
26
58
|
flexGrow: flexRatio,
|
|
27
59
|
flexShrink: flexRatio,
|
|
28
60
|
width: intrinsicWidth,
|
|
29
61
|
maxWidth: maxWidth
|
|
30
62
|
}}>
|
|
31
|
-
<div className=
|
|
32
|
-
<img src={previewSrc} alt="" loading="lazy" decoding="async" />
|
|
33
|
-
{!!more && <span className=
|
|
63
|
+
<div className="wy-image-area" style={{ paddingBottom: padding }}>
|
|
64
|
+
<img ref={imageRef} src={previewSrc} onLoad={imageLoaded} alt="" loading="lazy" decoding="async" />
|
|
65
|
+
{!!more && <span className="wy-more">+{more}</span>}
|
|
34
66
|
</div>
|
|
35
67
|
</a>
|
|
36
68
|
);
|
|
@@ -57,7 +89,7 @@ export const ImageGrid = ({ children, limit = 3}: ImageGridProps) => {
|
|
|
57
89
|
}
|
|
58
90
|
|
|
59
91
|
return (
|
|
60
|
-
<div className=
|
|
92
|
+
<div className="wy-image-grid">
|
|
61
93
|
{firstImages}
|
|
62
94
|
</div>
|
|
63
95
|
);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import Button from '../ui/Button';
|
|
3
3
|
import Icon from '../ui/Icon';
|
|
4
|
-
import { prefix as wy } from "../utils/styles";
|
|
5
4
|
|
|
6
5
|
type Props = {
|
|
7
6
|
meeting: MeetingCardType
|
|
@@ -14,13 +13,13 @@ const MeetingCard = ({ meeting }: Props) => {
|
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
return (
|
|
17
|
-
<div className=
|
|
18
|
-
<a className=
|
|
19
|
-
<div className=
|
|
20
|
-
<div className=
|
|
21
|
-
<div className=
|
|
22
|
-
<div className=
|
|
23
|
-
<Button.UI className=
|
|
16
|
+
<div className="wy-attachments">
|
|
17
|
+
<a className="wy-attachment" href={meeting.join_url} target="_blank">
|
|
18
|
+
<div className="wy-attachment-icon" title="Zoom meeting"><Icon.UI name="zoom" color="#4a8cff" size={4} /></div>
|
|
19
|
+
<div className="wy-attachment-content">
|
|
20
|
+
<div className="wy-attachment-title">Zoom meeting</div>
|
|
21
|
+
<div className="wy-attachment-meta">Meeting ID: {`${meeting.provider_id.substring(0,3)}-${meeting.provider_id.substring(3,6)}-${meeting.provider_id.substring(6)}`}</div>
|
|
22
|
+
<Button.UI className="wy-button-primary">Join meeting</Button.UI>
|
|
24
23
|
</div>
|
|
25
24
|
</a>
|
|
26
25
|
</div>
|
|
@@ -9,13 +9,12 @@ import SeenBy from './SeenBy';
|
|
|
9
9
|
import Avatar from "./Avatar";
|
|
10
10
|
import MeetingCard from './MeetingCard';
|
|
11
11
|
import usePreview from '../hooks/usePreview';
|
|
12
|
-
import
|
|
12
|
+
import classNames from 'classnames';
|
|
13
13
|
|
|
14
14
|
const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_at, attachments, meeting, parentId, reactions, seenBy }) => {
|
|
15
15
|
|
|
16
16
|
const { open, close } = usePreview(attachments);
|
|
17
17
|
|
|
18
|
-
var messageClassName = wy("message" + (me ? " message-me" : ""));
|
|
19
18
|
var images = attachments?.filter((a: AttachmentType) => a.kind === "image" && a.thumbnail_url);
|
|
20
19
|
var files = attachments?.filter((a: AttachmentType) => a.kind !== "image" || !a.thumbnail_url);
|
|
21
20
|
|
|
@@ -28,20 +27,20 @@ const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_a
|
|
|
28
27
|
|
|
29
28
|
return (
|
|
30
29
|
<>
|
|
31
|
-
<div className={
|
|
30
|
+
<div className={classNames("wy-message", { "wy-message-me": me })}>
|
|
32
31
|
{!me && (
|
|
33
|
-
<div className=
|
|
32
|
+
<div className="wy-message-author">
|
|
34
33
|
{avatar && <Avatar src={avatar} size={32} name={name} />}
|
|
35
34
|
</div>
|
|
36
35
|
)}
|
|
37
|
-
<div className=
|
|
38
|
-
<div className=
|
|
36
|
+
<div className="wy-message-content">
|
|
37
|
+
<div className="wy-message-meta">
|
|
39
38
|
<time dateTime={created_at} title={date.format('LLLL')}>{date.fromNow()}</time>
|
|
40
39
|
</div>
|
|
41
|
-
<div className=
|
|
42
|
-
<div className=
|
|
40
|
+
<div className="wy-message-content-row">
|
|
41
|
+
<div className="wy-message-bubble">
|
|
43
42
|
{temp &&
|
|
44
|
-
<div className=
|
|
43
|
+
<div className="wy-message-text">{html}</div>
|
|
45
44
|
}
|
|
46
45
|
{!temp &&
|
|
47
46
|
<>
|
|
@@ -51,13 +50,13 @@ const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_a
|
|
|
51
50
|
)}
|
|
52
51
|
</ImageGrid>}
|
|
53
52
|
|
|
54
|
-
{html && <div className=
|
|
53
|
+
{html && <div className="wy-message-text" dangerouslySetInnerHTML={{ __html: joypixels.shortnameToUnicode(html || "") }}></div>}
|
|
55
54
|
|
|
56
55
|
{meeting &&
|
|
57
56
|
<MeetingCard meeting={meeting} />
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
{files && !!files.length && <div className=
|
|
59
|
+
{files && !!files.length && <div className="wy-attachments">
|
|
61
60
|
{files.map((a: AttachmentType) =>
|
|
62
61
|
<Attachment key={a.id} name={a.name} previewFormat={a.kind} provider={a.provider} url={a.download_url} previewUrl={a.provider ? a.external_url : a.preview_url} mediaType={a.media_type} kind={a.kind} size={a.size} />
|
|
63
62
|
)}
|
|
@@ -66,13 +65,13 @@ const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_a
|
|
|
66
65
|
|
|
67
66
|
}
|
|
68
67
|
</div>
|
|
69
|
-
<div className=
|
|
68
|
+
<div className="wy-message-buttons">
|
|
70
69
|
{!temp && <ReactionsMenu id={id} reactions={reactions} />}
|
|
71
70
|
</div>
|
|
72
71
|
</div>
|
|
73
72
|
|
|
74
73
|
{!temp && (
|
|
75
|
-
<div className=
|
|
74
|
+
<div className="wy-reactions">
|
|
76
75
|
<ReactionsList id={id} parentId={parentId} reactions={reactions} />
|
|
77
76
|
</div>
|
|
78
77
|
)}
|
|
@@ -11,7 +11,6 @@ import useMutateRead from '../hooks/useMutateRead';
|
|
|
11
11
|
import useMutateMessage from '../hooks/useMutateMessage';
|
|
12
12
|
import { useQueryClient } from 'react-query';
|
|
13
13
|
import { WeavyContext } from '../contexts/WeavyContext';
|
|
14
|
-
import { prefix as wy } from "../utils/styles";
|
|
15
14
|
import Avatar from './Avatar';
|
|
16
15
|
|
|
17
16
|
type Props = {
|
|
@@ -198,16 +197,16 @@ const Messages = ({ id, members, displayName, avatarUrl }: Props) => {
|
|
|
198
197
|
readMessageMutation.mutate({ id: id, read: true })
|
|
199
198
|
}, [id]);
|
|
200
199
|
|
|
201
|
-
let messageHeader = <div className=
|
|
200
|
+
let messageHeader = <div className="wy-avatar-header">
|
|
202
201
|
{avatarUrl && displayName && <Avatar src={avatarUrl} name={displayName} id={id} size={128} /> || ''}
|
|
203
|
-
{displayName && <div className=
|
|
202
|
+
{displayName && <div className="wy-avatar-display-name">{displayName}</div> || ''}
|
|
204
203
|
</div>;
|
|
205
204
|
|
|
206
|
-
let loadMoreButton = <Button.UI onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} className=
|
|
205
|
+
let loadMoreButton = <Button.UI onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} className="wy-message-readmore">Load more</Button.UI>;
|
|
207
206
|
|
|
208
207
|
let messages = (
|
|
209
208
|
<>
|
|
210
|
-
<div className=
|
|
209
|
+
<div className="wy-message-readmore" ref={readMoreRef}>
|
|
211
210
|
{isFetchingNextPage
|
|
212
211
|
? 'Loading more...'
|
|
213
212
|
: hasNextPage
|
|
@@ -258,10 +257,10 @@ const Messages = ({ id, members, displayName, avatarUrl }: Props) => {
|
|
|
258
257
|
|
|
259
258
|
return (
|
|
260
259
|
<>
|
|
261
|
-
<div id="container" className=
|
|
260
|
+
<div id="container" className="wy-messages">
|
|
262
261
|
{messages}
|
|
263
262
|
</div>
|
|
264
|
-
<div className=
|
|
263
|
+
<div className="wy-message-editor">
|
|
265
264
|
<ConversationForm key={id} conversationId={id} handleInsert={handleNewMessage} />
|
|
266
265
|
</div>
|
|
267
266
|
</>
|
|
@@ -4,7 +4,6 @@ import Conversation from './Conversation';
|
|
|
4
4
|
import ConversationList from './ConversationList';
|
|
5
5
|
import { Messenger } from '../types/Messenger';
|
|
6
6
|
import { WeavyContext } from '../contexts/WeavyContext';
|
|
7
|
-
import { prefix as wy } from "../utils/styles";
|
|
8
7
|
|
|
9
8
|
const Messenger: FC<Messenger> = () => {
|
|
10
9
|
|
|
@@ -16,13 +15,13 @@ const Messenger: FC<Messenger> = () => {
|
|
|
16
15
|
|
|
17
16
|
return (
|
|
18
17
|
<MessengerProvider>
|
|
19
|
-
<div className=
|
|
18
|
+
<div className="wy-messenger-provider">
|
|
20
19
|
|
|
21
|
-
<div className=
|
|
20
|
+
<div className="wy-messenger-sidebar wy-scroll-y">
|
|
22
21
|
<ConversationList />
|
|
23
22
|
</div>
|
|
24
23
|
|
|
25
|
-
<div className=
|
|
24
|
+
<div className="wy-messenger-conversation wy-scroll-y">
|
|
26
25
|
<Conversation id={null} />
|
|
27
26
|
</div>
|
|
28
27
|
</div>
|
|
@@ -4,7 +4,6 @@ import Icon from '../ui/Icon';
|
|
|
4
4
|
import Overlay from '../ui/Overlay';
|
|
5
5
|
import Button from '../ui/Button';
|
|
6
6
|
import SearchUsers from './SearchUsers';
|
|
7
|
-
import { prefix as wy } from "../utils/styles";
|
|
8
7
|
|
|
9
8
|
const NewConversation = () => {
|
|
10
9
|
const [modalOpen, setModalOpen] = useState(false);
|
|
@@ -27,18 +26,17 @@ const NewConversation = () => {
|
|
|
27
26
|
|
|
28
27
|
return (
|
|
29
28
|
<>
|
|
30
|
-
|
|
31
29
|
<Button.UI onClick={handleOpen}><Icon.UI name="plus" /></Button.UI>
|
|
32
30
|
|
|
33
|
-
<Overlay.UI isOpen={modalOpen} className=
|
|
34
|
-
<header className=
|
|
35
|
-
<nav className=
|
|
31
|
+
<Overlay.UI isOpen={modalOpen} className="wy-modal">
|
|
32
|
+
<header className="wy-appbars">
|
|
33
|
+
<nav className="wy-appbar">
|
|
36
34
|
<Button.UI onClick={handleClose}><Icon.UI name='close' /></Button.UI>
|
|
37
|
-
<div className=
|
|
35
|
+
<div className="wy-appbar-text">Create conversation</div>
|
|
38
36
|
</nav>
|
|
39
37
|
</header>
|
|
40
38
|
|
|
41
|
-
<SearchUsers handleSubmit={handleCreate} buttonTitle="
|
|
39
|
+
<SearchUsers handleSubmit={handleCreate} buttonTitle="Next"/>
|
|
42
40
|
</Overlay.UI>
|
|
43
41
|
</>
|
|
44
42
|
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useCallback, useState } from "react";
|
|
2
|
+
import pdfjsLib from 'pdfjs-dist';
|
|
3
|
+
import pdfjsViewer from 'pdfjs-dist/web/pdf_viewer';
|
|
4
|
+
import Icon from "../ui/Icon";
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
src: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const PdfViewer = ({ src }: Props) => {
|
|
11
|
+
//const viewerRef = useRef(null);
|
|
12
|
+
const pageNumberRef = useRef<HTMLInputElement>(null);
|
|
13
|
+
const totalPagesRef = useRef<HTMLSpanElement>(null);
|
|
14
|
+
const zoomLevelRef = useRef<HTMLInputElement>(null);
|
|
15
|
+
|
|
16
|
+
const [pdfEventBus, setPdfEventBus] = useState<pdfjsViewer.EventBus>();
|
|
17
|
+
|
|
18
|
+
const [pdfViewer, setPdfViewer] = useState<pdfjsViewer.PDFViewer>();
|
|
19
|
+
const [pdfLinkService, setPdfLinkService] = useState<pdfjsViewer.PDFLinkService>();
|
|
20
|
+
const [pdfFindController, setPdfFindController] = useState<pdfjsViewer.PDFFindController>();
|
|
21
|
+
|
|
22
|
+
const DEFAULT_SCALE_DELTA = 1.1;
|
|
23
|
+
const MAX_SCALE = 3.0;
|
|
24
|
+
const MIN_SCALE = 0.2;
|
|
25
|
+
|
|
26
|
+
const SEARCH_FOR = "";
|
|
27
|
+
const ENABLE_XFA = true;
|
|
28
|
+
|
|
29
|
+
// Some PDFs need external cmaps.
|
|
30
|
+
const CMAP_URL = "/cmaps/";
|
|
31
|
+
const CMAP_PACKED = true;
|
|
32
|
+
|
|
33
|
+
// Setting worker path to worker bundle.
|
|
34
|
+
pdfjsLib.GlobalWorkerOptions.workerSrc = "/js/pdf.worker.min.js";
|
|
35
|
+
|
|
36
|
+
const viewerRef = useCallback((container: any) => {
|
|
37
|
+
if (container !== null) {
|
|
38
|
+
|
|
39
|
+
let linkService = pdfLinkService;
|
|
40
|
+
let findController = pdfFindController;
|
|
41
|
+
let viewer = pdfViewer;
|
|
42
|
+
let eventBus = pdfEventBus;
|
|
43
|
+
|
|
44
|
+
if (!pdfEventBus) {
|
|
45
|
+
eventBus = new pdfjsViewer.EventBus();
|
|
46
|
+
setPdfEventBus(eventBus);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// (Optionally) enable hyperlinks within PDF files.
|
|
50
|
+
if (!pdfLinkService) {
|
|
51
|
+
linkService = new pdfjsViewer.PDFLinkService({
|
|
52
|
+
eventBus: eventBus!,
|
|
53
|
+
})
|
|
54
|
+
setPdfLinkService(linkService);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// (Optionally) enable find controller.
|
|
58
|
+
if (!pdfFindController) {
|
|
59
|
+
findController = new pdfjsViewer.PDFFindController({
|
|
60
|
+
eventBus: eventBus!,
|
|
61
|
+
linkService: linkService!,
|
|
62
|
+
})
|
|
63
|
+
setPdfFindController(findController);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!pdfViewer && eventBus) {
|
|
67
|
+
// @ts-ignore due to incorrect type def
|
|
68
|
+
viewer = new pdfjsViewer.PDFViewer({
|
|
69
|
+
container: container,
|
|
70
|
+
eventBus: eventBus,
|
|
71
|
+
linkService: linkService!,
|
|
72
|
+
findController: findController,
|
|
73
|
+
//defaultZoomValue: 1.0,
|
|
74
|
+
//scriptingManager: pdfScriptingManager,
|
|
75
|
+
//enableScripting: true, // Only necessary in PDF.js version 2.10.377 and below.
|
|
76
|
+
})
|
|
77
|
+
//pdfViewer!.MAX_AUTO_SCALE = 1.0;
|
|
78
|
+
linkService!.setViewer(viewer);
|
|
79
|
+
setPdfViewer(viewer);
|
|
80
|
+
|
|
81
|
+
eventBus.on("scalechanging", function () {
|
|
82
|
+
console.debug("scalechanging")
|
|
83
|
+
zoomLevelRef.current!.value = (Math.round(viewer!.currentScale * 100)).toFixed(0) + "%";
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
eventBus.on("pagechanging", function () {
|
|
87
|
+
console.debug("pagechanging")
|
|
88
|
+
if (pageNumberRef.current) {
|
|
89
|
+
pageNumberRef.current.value = viewer!.currentPageNumber.toFixed(0);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
eventBus.on("pagesinit", function () {
|
|
94
|
+
// We can use pdfViewer now, e.g. let's change default scale.
|
|
95
|
+
viewer!.currentScaleValue = "auto";
|
|
96
|
+
pageNumberRef.current!.value = "1";
|
|
97
|
+
totalPagesRef.current!.innerText = viewer!.pagesCount.toFixed(0);
|
|
98
|
+
|
|
99
|
+
// We can try searching for things.
|
|
100
|
+
if (SEARCH_FOR) {
|
|
101
|
+
if (findController && !("_onFind" in findController)) {
|
|
102
|
+
// @ts-ignore due to missing type def
|
|
103
|
+
findController.executeCommand("find", { query: SEARCH_FOR });
|
|
104
|
+
} else {
|
|
105
|
+
eventBus!.dispatch("find", { type: "", query: SEARCH_FOR });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
} else {
|
|
112
|
+
console.warn("pdf viewer dismounted")
|
|
113
|
+
}
|
|
114
|
+
}, []);
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (src && pdfViewer && pdfLinkService) {
|
|
118
|
+
let loadingTask: pdfjsLib.PDFDocumentLoadingTask;
|
|
119
|
+
let loadedDoc: pdfjsLib.PDFDocumentProxy;
|
|
120
|
+
|
|
121
|
+
loadingTask = pdfjsLib.getDocument({
|
|
122
|
+
url: src,
|
|
123
|
+
enableXfa: ENABLE_XFA,
|
|
124
|
+
cMapUrl: CMAP_URL,
|
|
125
|
+
cMapPacked: CMAP_PACKED,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Re-use the worker?
|
|
129
|
+
//pdfjsLib.GlobalWorkerOptions.workerPort = loadingTask._worker.port
|
|
130
|
+
|
|
131
|
+
loadingTask.promise.then(function (doc) {
|
|
132
|
+
loadedDoc = doc;
|
|
133
|
+
//console.log("LOADED PDF");
|
|
134
|
+
pdfViewer.setDocument(doc);
|
|
135
|
+
pdfLinkService.setDocument(doc, null);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return () => {
|
|
139
|
+
if (loadingTask) {
|
|
140
|
+
console.log("resetting pdf viewer");
|
|
141
|
+
if(loadingTask._transport){
|
|
142
|
+
loadingTask._transport.destroy();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (loadedDoc) {
|
|
146
|
+
loadedDoc.destroy();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
//loadingTask.destroy();
|
|
150
|
+
pdfViewer.cleanup();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}, [src, pdfViewer])
|
|
155
|
+
|
|
156
|
+
function setScale(scale: number | string) {
|
|
157
|
+
console.debug("setScale:", scale)
|
|
158
|
+
if (pdfViewer) {
|
|
159
|
+
pdfViewer.currentScaleValue = typeof scale === "number" ? scale.toFixed(2) : scale;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function setPage(pageNumber: number) {
|
|
164
|
+
console.debug("setPage:", pageNumber)
|
|
165
|
+
if (pdfViewer) {
|
|
166
|
+
pdfViewer.currentPageNumber = pageNumber;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function updatePage() {
|
|
171
|
+
console.debug("updatePage");
|
|
172
|
+
if (pdfViewer && pageNumberRef.current) {
|
|
173
|
+
let pageNumber = parseInt(pageNumberRef.current.value);
|
|
174
|
+
|
|
175
|
+
if (isNaN(pageNumber)) {
|
|
176
|
+
setPage(pdfViewer.currentPageNumber);
|
|
177
|
+
} else if (pageNumber > pdfViewer.pagesCount) {
|
|
178
|
+
setPage(pdfViewer.pagesCount);
|
|
179
|
+
} else if (pageNumber <= 0) {
|
|
180
|
+
setPage(1);
|
|
181
|
+
} else {
|
|
182
|
+
setPage(pageNumber);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function select(e: any) {
|
|
189
|
+
console.debug("select");
|
|
190
|
+
e.target.setSelectionRange(0, e.target.value.length);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function fitToPage() {
|
|
194
|
+
setScale("page-fit");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function fitToWidth() {
|
|
198
|
+
setScale("page-width");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function zoomIn() {
|
|
202
|
+
console.debug("zoomIn");
|
|
203
|
+
|
|
204
|
+
if (pdfViewer) {
|
|
205
|
+
let newScale = pdfViewer.currentScale;
|
|
206
|
+
let steps = 1;
|
|
207
|
+
do {
|
|
208
|
+
newScale = newScale * DEFAULT_SCALE_DELTA;
|
|
209
|
+
newScale = Math.floor(newScale * 10) / 10;
|
|
210
|
+
newScale = Math.min(MAX_SCALE, newScale);
|
|
211
|
+
} while (--steps > 0 && newScale < MAX_SCALE);
|
|
212
|
+
|
|
213
|
+
setScale(newScale);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function zoomOut() {
|
|
218
|
+
console.debug("zoomOut");
|
|
219
|
+
if (pdfViewer) {
|
|
220
|
+
let newScale = pdfViewer.currentScale;
|
|
221
|
+
let steps = 1;
|
|
222
|
+
do {
|
|
223
|
+
newScale = newScale / DEFAULT_SCALE_DELTA;
|
|
224
|
+
newScale = Math.floor(newScale * 10) / 10;
|
|
225
|
+
newScale = Math.max(MIN_SCALE, newScale);
|
|
226
|
+
} while (--steps > 0 && newScale > MIN_SCALE);
|
|
227
|
+
|
|
228
|
+
setScale(newScale);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function updateZoom() {
|
|
233
|
+
console.debug("updateZoom");
|
|
234
|
+
if (pdfViewer && zoomLevelRef.current) {
|
|
235
|
+
let zoomValue = parseFloat(zoomLevelRef.current.value.replace("%", ""));
|
|
236
|
+
if (isNaN(zoomValue)) {
|
|
237
|
+
setScale(pdfViewer.currentScale + 0.0001);
|
|
238
|
+
} else {
|
|
239
|
+
setScale(zoomValue / 100);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return (
|
|
245
|
+
<div className="wy-content-pdf" data-controller="pdf" data-pdf-url-value="">
|
|
246
|
+
<div className="wy-toolbar">
|
|
247
|
+
<nav className="wy-tools">
|
|
248
|
+
<div className="wy-tool">
|
|
249
|
+
<input type="text" className="wy-input" ref={pageNumberRef} onChange={updatePage} onClick={select} data-pdf-target="pageNumber"/>
|
|
250
|
+
<span>/</span>
|
|
251
|
+
<span ref={totalPagesRef}>1</span>
|
|
252
|
+
</div>
|
|
253
|
+
<div className="wy-tool">
|
|
254
|
+
<button className="wy-button wy-button-icon btn-zoom-out" onClick={zoomOut} title="Zoom out"><Icon.UI name="minus" /></button>
|
|
255
|
+
<input type="text" className="wy-input" ref={zoomLevelRef} onChange={updateZoom} onClick={select} value="100%" data-pdf-target="zoomLevel"/>
|
|
256
|
+
<button className="wy-button wy-button-icon btn-zoom-in" onClick={zoomIn} title="Zoom in"><Icon.UI name="plus" /></button>
|
|
257
|
+
</div>
|
|
258
|
+
<div className="wy-tool">
|
|
259
|
+
<button className="wy-button wy-button-icon btn-fit-page" onClick={fitToWidth} title="Fit to width"><Icon.UI name="fit-width" /></button>
|
|
260
|
+
<button className="wy-button wy-button-icon" onClick={fitToPage} title="Fit to screen"><Icon.UI name="fit-screen" /></button>
|
|
261
|
+
</div>
|
|
262
|
+
</nav>
|
|
263
|
+
</div>
|
|
264
|
+
<div ref={viewerRef} className="wy-pdf-container">
|
|
265
|
+
<div id="viewer" className="pdfViewer"></div>
|
|
266
|
+
</div>
|
|
267
|
+
</div>
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export default PdfViewer;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
2
|
+
import classNames from "classnames";
|
|
3
3
|
|
|
4
4
|
type Props = {
|
|
5
5
|
id: number,
|
|
@@ -8,7 +8,7 @@ type Props = {
|
|
|
8
8
|
|
|
9
9
|
const Presence = ({ id, status }: Props) => {
|
|
10
10
|
return (
|
|
11
|
-
<span className={wy
|
|
11
|
+
<span className={classNames("wy-presence", { "wy-presence-active": status === "active" })} data-presence-id={id}></span>
|
|
12
12
|
)
|
|
13
13
|
}
|
|
14
14
|
|