Преглед изворни кода

Merge pull request #20715 from overleaf/ii-bs5-chat-pane

[web] BS5 chat pane

GitOrigin-RevId: 8587aca1372b4d2087863d492e702f04a31c23e2
ilkin-overleaf пре 2 година
родитељ
комит
6c7ee8f778

+ 5 - 4
services/web/frontend/js/features/chat/components/chat-fallback-error.jsx

@@ -1,6 +1,7 @@
 import PropTypes from 'prop-types'
 import { useTranslation } from 'react-i18next'
-import { Button, Alert } from 'react-bootstrap'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
+import OLButton from '@/features/ui/components/ol/ol-button'
 
 function ChatFallbackError({ reconnect }) {
   const { t } = useTranslation()
@@ -8,12 +9,12 @@ function ChatFallbackError({ reconnect }) {
   return (
     <aside className="chat">
       <div className="chat-error">
-        <Alert bsStyle="danger">{t('chat_error')}</Alert>
+        <OLNotification type="error" content={t('chat_error')} />
         {reconnect && (
           <p className="text-center">
-            <Button bsStyle="info" type="button" onClick={reconnect}>
+            <OLButton variant="secondary" onClick={reconnect}>
               {t('reconnect')}
-            </Button>
+            </OLButton>
           </p>
         )}
       </div>

+ 10 - 2
services/web/frontend/js/features/chat/components/chat-pane.tsx

@@ -11,6 +11,9 @@ import withErrorBoundary from '../../../infrastructure/error-boundary'
 import { FetchError } from '../../../infrastructure/fetch-json'
 import { useChatContext } from '../context/chat-context'
 import LoadingSpinner from '../../../shared/components/loading-spinner'
+import { bsVersion } from '@/features/utils/bootstrap-5'
+import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
+import MaterialIcon from '@/shared/components/material-icon'
 
 const MessageList = lazy(() => import('./message-list'))
 
@@ -79,7 +82,9 @@ const ChatPane = React.memo(function ChatPane() {
         itemCount={messageContentCount}
       >
         <div>
-          <h2 className="sr-only">{t('chat')}</h2>
+          <h2 className={bsVersion({ bs3: 'sr-only', bs5: 'visually-hidden' })}>
+            {t('chat')}
+          </h2>
           <Suspense fallback={<LoadingSpinner delay={500} />}>
             {status === 'pending' && <LoadingSpinner delay={500} />}
             {shouldDisplayPlaceholder && <Placeholder />}
@@ -107,7 +112,10 @@ function Placeholder() {
       <div className="first-message text-center">
         {t('send_first_message')}
         <br />
-        <Icon type="arrow-down" />
+        <BootstrapVersionSwitcher
+          bs3={<Icon type="arrow-down" />}
+          bs5={<MaterialIcon type="arrow_downward" />}
+        />
       </div>
     </>
   )

+ 5 - 1
services/web/frontend/js/features/chat/components/message-input.tsx

@@ -1,4 +1,5 @@
 import { useTranslation } from 'react-i18next'
+import { bsVersion } from '@/features/utils/bootstrap-5'
 
 type MessageInputProps = {
   resetUnreadMessages: () => void
@@ -26,7 +27,10 @@ function MessageInput({ resetUnreadMessages, sendMessage }: MessageInputProps) {
 
   return (
     <form className="new-message">
-      <label htmlFor="chat-input" className="sr-only">
+      <label
+        htmlFor="chat-input"
+        className={bsVersion({ bs3: 'sr-only', bs5: 'visually-hidden' })}
+      >
         {t('your_message_to_collaborators')}
       </label>
       <textarea

+ 1 - 1
services/web/frontend/js/shared/components/loading-spinner.tsx

@@ -44,7 +44,7 @@ function LoadingSpinner({
             animation="border"
             aria-hidden="true"
             role="status"
-            className="align-bottom"
+            className="align-middle"
           />
           &nbsp;
           {loadingText || t('loading')}…

+ 0 - 10
services/web/frontend/stylesheets/app/editor/chat.less

@@ -1,11 +1,5 @@
 @new-message-height: 80px;
 
-#chat-wrapper {
-  > .ui-layout-resizer > .ui-layout-toggler {
-    display: none !important;
-  }
-}
-
 .chat {
   .loading {
     font-family: @font-family-serif;
@@ -140,7 +134,3 @@
     }
   }
 }
-
-.break-word {
-  word-break: break-all;
-}

+ 1 - 0
services/web/frontend/stylesheets/bootstrap-5/abstracts/all.scss

@@ -1,3 +1,4 @@
 @import 'mixins';
 @import 'variables';
 @import 'variable-overrides';
+@import 'themes-common-variables';

+ 7 - 0
services/web/frontend/stylesheets/bootstrap-5/abstracts/themes-common-variables.scss

@@ -0,0 +1,7 @@
+:root {
+  --editor-border-color: var(--neutral-80);
+}
+
+@include theme('light') {
+  --editor-border-color: var(--neutral-20);
+}

+ 1 - 0
services/web/frontend/stylesheets/bootstrap-5/pages/all.scss

@@ -11,6 +11,7 @@
 @import 'editor/outline';
 @import 'editor/file-tree';
 @import 'editor/figure-modal';
+@import 'editor/chat';
 @import 'subscription';
 @import 'editor/pdf';
 @import 'editor/compile-button';

+ 165 - 0
services/web/frontend/stylesheets/bootstrap-5/pages/editor/chat.scss

@@ -0,0 +1,165 @@
+:root {
+  --chat-bg: var(--neutral-80);
+  --chat-color: var(--white);
+  --chat-instructions-color: var(--neutral-20);
+  --chat-new-message-bg: var(--neutral-70);
+  --chat-new-message-textarea-color: var(--neutral-90);
+  --chat-new-message-textarea-bg: var(--neutral-20);
+  --chat-message-date-color: var(--neutral-40);
+  --chat-message-name-color: var(--white);
+}
+
+@include theme('light') {
+  --chat-bg: var(--white);
+  --chat-color: var(--neutral-70);
+  --chat-instructions-color: var(--neutral-70);
+  --chat-new-message-bg: var(--neutral-10);
+  --chat-new-message-textarea-color: var(--neutral-90);
+  --chat-new-message-textarea-bg: var(--white);
+  --chat-message-date-color: var(--neutral-70);
+  --chat-message-name-color: var(--neutral-70);
+}
+
+.chat {
+  $new-message-height: 80px;
+
+  color: var(--chat-color);
+
+  .no-messages {
+    padding: calc(var(--line-height-03) / 2);
+    color: var(--chat-instructions-color);
+  }
+
+  .first-message {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    padding: calc(var(--line-height-03) / 2);
+    color: var(--chat-instructions-color);
+  }
+
+  .chat-error {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    background-color: var(--chat-bg);
+    padding: calc(var(--line-height-03) / 2);
+    text-align: center;
+  }
+
+  .messages {
+    position: absolute;
+    inset: 0;
+    bottom: $new-message-height;
+    overflow-x: hidden;
+    background-color: var(--chat-bg);
+
+    li.message {
+      margin: calc(var(--line-height-03) / 2);
+
+      .date {
+        font-size: var(--font-size-01);
+        color: var(--chat-message-date-color);
+        margin-bottom: calc(var(--line-height-03) / 2);
+        text-align: right;
+      }
+
+      .message-wrapper {
+        .name {
+          font-size: var(--font-size-01);
+          color: var(--chat-message-name-color);
+          margin-bottom: var(--spacing-02);
+          min-height: 16px;
+        }
+
+        .message {
+          border-left: 3px solid transparent;
+          font-size: var(--font-size-02);
+          box-shadow: none;
+          border-radius: var(--border-radius-base);
+          position: relative;
+
+          .message-content {
+            padding: var(--spacing-03) var(--spacing-05);
+            overflow-x: auto;
+            color: var(--white);
+            font-weight: bold;
+
+            a {
+              color: var(--white);
+            }
+          }
+
+          .arrow {
+            transform: rotate(90deg);
+            right: 90%;
+            top: -15px;
+            border: solid;
+            content: ' ';
+            height: 0;
+            width: 0;
+            position: absolute;
+            pointer-events: none;
+            border-top-color: transparent !important;
+            border-bottom-color: transparent !important;
+            border-width: 10px;
+          }
+        }
+
+        p {
+          margin-bottom: calc(var(--line-height-03) / 4);
+
+          &:last-child {
+            margin-bottom: 0;
+          }
+        }
+      }
+
+      &:not(.self) {
+        .message {
+          .arrow {
+            border-left-color: transparent !important;
+          }
+        }
+      }
+
+      &.self {
+        margin-top: var(--line-height-03);
+
+        .message-wrapper .message {
+          border-left: none;
+          border-right: 3px solid transparent;
+
+          .arrow {
+            left: 100%;
+            right: auto;
+            border-right-color: transparent !important;
+          }
+        }
+      }
+    }
+  }
+
+  .new-message {
+    @extend .full-size;
+
+    top: auto;
+    height: $new-message-height;
+    background-color: var(--chat-new-message-bg);
+    padding: calc(var(--line-height-03) / 4);
+    border-top: 1px solid var(--editor-border-color);
+
+    textarea {
+      overflow: auto;
+      resize: none;
+      border-radius: var(--border-radius-base);
+      border: 1px solid var(--editor-border-color);
+      height: 100%;
+      width: 100%;
+      color: var(--chat-new-message-textarea-color);
+      font-size: var(--font-size-02);
+      padding: calc(var(--line-height-03) / 4);
+      background-color: var(--chat-new-message-textarea-bg);
+    }
+  }
+}