mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	Merge pull request #2131 from Yidadaa/bugfix-0625
feat: close #1615 pin messages to contextual prompts
This commit is contained in:
		@@ -3,6 +3,7 @@
 | 
			
		||||
.chat-input-actions {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-wrap: wrap;
 | 
			
		||||
  margin-bottom: 10px;
 | 
			
		||||
 | 
			
		||||
  .chat-input-action {
 | 
			
		||||
    display: inline-flex;
 | 
			
		||||
@@ -15,7 +16,6 @@
 | 
			
		||||
    animation: slide-in ease 0.3s;
 | 
			
		||||
    box-shadow: var(--card-shadow);
 | 
			
		||||
    transition: all ease 0.3s;
 | 
			
		||||
    margin-bottom: 10px;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    height: 16px;
 | 
			
		||||
    width: var(--icon-width);
 | 
			
		||||
@@ -202,3 +202,225 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-body {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  padding: 20px;
 | 
			
		||||
  padding-bottom: 40px;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  overscroll-behavior: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-body-title {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
 | 
			
		||||
  &:hover {
 | 
			
		||||
    text-decoration: underline;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
 | 
			
		||||
  &:last-child {
 | 
			
		||||
    animation: slide-in ease 0.3s;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-user {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row-reverse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-container {
 | 
			
		||||
  max-width: var(--message-max-width);
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  align-items: flex-start;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-user > .chat-message-container {
 | 
			
		||||
  align-items: flex-end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-avatar {
 | 
			
		||||
  margin-top: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-status {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  color: #aaa;
 | 
			
		||||
  line-height: 1.5;
 | 
			
		||||
  margin-top: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-item {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
  margin-top: 10px;
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  background-color: rgba(0, 0, 0, 0.05);
 | 
			
		||||
  padding: 10px;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  user-select: text;
 | 
			
		||||
  word-break: break-word;
 | 
			
		||||
  border: var(--border-in-light);
 | 
			
		||||
  position: relative;
 | 
			
		||||
  transition: all ease 0.3s;
 | 
			
		||||
  min-width: 0;
 | 
			
		||||
 | 
			
		||||
  &:hover {
 | 
			
		||||
    min-width: 330px;
 | 
			
		||||
 | 
			
		||||
    .chat-message-actions {
 | 
			
		||||
      height: 40px;
 | 
			
		||||
      opacity: 1;
 | 
			
		||||
      transform: translateY(0px);
 | 
			
		||||
 | 
			
		||||
      .chat-message-action-date {
 | 
			
		||||
        opacity: 0.3;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .chat-message-actions {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    align-items: flex-end;
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
    transition: all ease 0.3s;
 | 
			
		||||
    transform: translateY(10px);
 | 
			
		||||
    opacity: 0;
 | 
			
		||||
    height: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .chat-message-action-date {
 | 
			
		||||
    color: var(--black);
 | 
			
		||||
    opacity: 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-user > .chat-message-container > .chat-message-item {
 | 
			
		||||
  background-color: var(--second);
 | 
			
		||||
 | 
			
		||||
  &:hover {
 | 
			
		||||
    min-width: 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input-panel {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  padding: 20px;
 | 
			
		||||
  padding-top: 10px;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  border-top: var(--border-in-light);
 | 
			
		||||
  box-shadow: var(--card-shadow);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin single-line {
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.prompt-hints {
 | 
			
		||||
  min-height: 20px;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  max-height: 50vh;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column-reverse;
 | 
			
		||||
 | 
			
		||||
  background-color: var(--white);
 | 
			
		||||
  border: var(--border-in-light);
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  margin-bottom: 10px;
 | 
			
		||||
  box-shadow: var(--shadow);
 | 
			
		||||
 | 
			
		||||
  .prompt-hint {
 | 
			
		||||
    color: var(--black);
 | 
			
		||||
    padding: 6px 10px;
 | 
			
		||||
    animation: slide-in ease 0.3s;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    transition: all ease 0.3s;
 | 
			
		||||
    border: transparent 1px solid;
 | 
			
		||||
    margin: 4px;
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
 | 
			
		||||
    &:not(:last-child) {
 | 
			
		||||
      margin-top: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .hint-title {
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
      font-weight: bolder;
 | 
			
		||||
 | 
			
		||||
      @include single-line();
 | 
			
		||||
    }
 | 
			
		||||
    .hint-content {
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
 | 
			
		||||
      @include single-line();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &-selected,
 | 
			
		||||
    &:hover {
 | 
			
		||||
      border-color: var(--primary);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input-panel-inner {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  border: var(--border-in-light);
 | 
			
		||||
  box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.03);
 | 
			
		||||
  background-color: var(--white);
 | 
			
		||||
  color: var(--black);
 | 
			
		||||
  font-family: inherit;
 | 
			
		||||
  padding: 10px 90px 10px 14px;
 | 
			
		||||
  resize: none;
 | 
			
		||||
  outline: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input:focus {
 | 
			
		||||
  border: 1px solid var(--primary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input-send {
 | 
			
		||||
  background-color: var(--primary);
 | 
			
		||||
  color: white;
 | 
			
		||||
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 30px;
 | 
			
		||||
  bottom: 32px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media only screen and (max-width: 600px) {
 | 
			
		||||
  .chat-input {
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .chat-input-send {
 | 
			
		||||
    bottom: 30px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,8 @@ import MinIcon from "../icons/min.svg";
 | 
			
		||||
import ResetIcon from "../icons/reload.svg";
 | 
			
		||||
import BreakIcon from "../icons/break.svg";
 | 
			
		||||
import SettingsIcon from "../icons/chat-settings.svg";
 | 
			
		||||
import DeleteIcon from "../icons/clear.svg";
 | 
			
		||||
import PinIcon from "../icons/pin.svg";
 | 
			
		||||
 | 
			
		||||
import LightIcon from "../icons/light.svg";
 | 
			
		||||
import DarkIcon from "../icons/dark.svg";
 | 
			
		||||
@@ -57,10 +59,9 @@ import { Prompt, usePromptStore } from "../store/prompt";
 | 
			
		||||
import Locale from "../locales";
 | 
			
		||||
 | 
			
		||||
import { IconButton } from "./button";
 | 
			
		||||
import styles from "./home.module.scss";
 | 
			
		||||
import chatStyle from "./chat.module.scss";
 | 
			
		||||
import styles from "./chat.module.scss";
 | 
			
		||||
 | 
			
		||||
import { ListItem, Modal } from "./ui-lib";
 | 
			
		||||
import { ListItem, Modal, showToast } from "./ui-lib";
 | 
			
		||||
import { useLocation, useNavigate } from "react-router-dom";
 | 
			
		||||
import { LAST_INPUT_KEY, Path, REQUEST_TIMEOUT_MS } from "../constant";
 | 
			
		||||
import { Avatar } from "./emoji";
 | 
			
		||||
@@ -148,15 +149,15 @@ function PromptToast(props: {
 | 
			
		||||
  const context = session.mask.context;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={chatStyle["prompt-toast"]} key="prompt-toast">
 | 
			
		||||
    <div className={styles["prompt-toast"]} key="prompt-toast">
 | 
			
		||||
      {props.showToast && (
 | 
			
		||||
        <div
 | 
			
		||||
          className={chatStyle["prompt-toast-inner"] + " clickable"}
 | 
			
		||||
          className={styles["prompt-toast-inner"] + " clickable"}
 | 
			
		||||
          role="button"
 | 
			
		||||
          onClick={() => props.setShowModal(true)}
 | 
			
		||||
        >
 | 
			
		||||
          <BrainIcon />
 | 
			
		||||
          <span className={chatStyle["prompt-toast-content"]}>
 | 
			
		||||
          <span className={styles["prompt-toast-content"]}>
 | 
			
		||||
            {Locale.Context.Toast(context.length)}
 | 
			
		||||
          </span>
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -270,17 +271,15 @@ function ClearContextDivider() {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      className={chatStyle["clear-context"]}
 | 
			
		||||
      className={styles["clear-context"]}
 | 
			
		||||
      onClick={() =>
 | 
			
		||||
        chatStore.updateCurrentSession(
 | 
			
		||||
          (session) => (session.clearContextIndex = undefined),
 | 
			
		||||
        )
 | 
			
		||||
      }
 | 
			
		||||
    >
 | 
			
		||||
      <div className={chatStyle["clear-context-tips"]}>
 | 
			
		||||
        {Locale.Context.Clear}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className={chatStyle["clear-context-revert-btn"]}>
 | 
			
		||||
      <div className={styles["clear-context-tips"]}>{Locale.Context.Clear}</div>
 | 
			
		||||
      <div className={styles["clear-context-revert-btn"]}>
 | 
			
		||||
        {Locale.Context.Revert}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -316,7 +315,7 @@ function ChatAction(props: {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      className={`${chatStyle["chat-input-action"]} clickable`}
 | 
			
		||||
      className={`${styles["chat-input-action"]} clickable`}
 | 
			
		||||
      onClick={() => {
 | 
			
		||||
        props.onClick();
 | 
			
		||||
        setTimeout(updateWidth, 1);
 | 
			
		||||
@@ -328,10 +327,10 @@ function ChatAction(props: {
 | 
			
		||||
        } as React.CSSProperties
 | 
			
		||||
      }
 | 
			
		||||
    >
 | 
			
		||||
      <div ref={iconRef} className={chatStyle["icon"]}>
 | 
			
		||||
      <div ref={iconRef} className={styles["icon"]}>
 | 
			
		||||
        {props.icon}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className={chatStyle["text"]} ref={textRef}>
 | 
			
		||||
      <div className={styles["text"]} ref={textRef}>
 | 
			
		||||
        {props.text}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -400,7 +399,7 @@ export function ChatActions(props: {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={chatStyle["chat-input-actions"]}>
 | 
			
		||||
    <div className={styles["chat-input-actions"]}>
 | 
			
		||||
      {couldStop && (
 | 
			
		||||
        <ChatAction
 | 
			
		||||
          onClick={stopAll}
 | 
			
		||||
@@ -698,6 +697,24 @@ export function Chat() {
 | 
			
		||||
    inputRef.current?.focus();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const onPinMessage = (botMessage: ChatMessage) => {
 | 
			
		||||
    if (!botMessage.id) return;
 | 
			
		||||
    const userMessageIndex = findLastUserIndex(botMessage.id);
 | 
			
		||||
    if (!userMessageIndex) return;
 | 
			
		||||
 | 
			
		||||
    const userMessage = session.messages[userMessageIndex];
 | 
			
		||||
    chatStore.updateCurrentSession((session) =>
 | 
			
		||||
      session.mask.context.push(userMessage, botMessage),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    showToast(Locale.Chat.Actions.PinToastContent, {
 | 
			
		||||
      text: Locale.Chat.Actions.PinToastAction,
 | 
			
		||||
      onClick: () => {
 | 
			
		||||
        setShowPromptModal(true);
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const context: RenderMessage[] = session.mask.hideContext
 | 
			
		||||
    ? []
 | 
			
		||||
    : session.mask.context.slice();
 | 
			
		||||
@@ -880,40 +897,6 @@ export function Chat() {
 | 
			
		||||
                    </div>
 | 
			
		||||
                  )}
 | 
			
		||||
                  <div className={styles["chat-message-item"]}>
 | 
			
		||||
                    {showActions && (
 | 
			
		||||
                      <div className={styles["chat-message-top-actions"]}>
 | 
			
		||||
                        {message.streaming ? (
 | 
			
		||||
                          <div
 | 
			
		||||
                            className={styles["chat-message-top-action"]}
 | 
			
		||||
                            onClick={() => onUserStop(message.id ?? i)}
 | 
			
		||||
                          >
 | 
			
		||||
                            {Locale.Chat.Actions.Stop}
 | 
			
		||||
                          </div>
 | 
			
		||||
                        ) : (
 | 
			
		||||
                          <>
 | 
			
		||||
                            <div
 | 
			
		||||
                              className={styles["chat-message-top-action"]}
 | 
			
		||||
                              onClick={() => onDelete(message.id ?? i)}
 | 
			
		||||
                            >
 | 
			
		||||
                              {Locale.Chat.Actions.Delete}
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div
 | 
			
		||||
                              className={styles["chat-message-top-action"]}
 | 
			
		||||
                              onClick={() => onResend(message.id ?? i)}
 | 
			
		||||
                            >
 | 
			
		||||
                              {Locale.Chat.Actions.Retry}
 | 
			
		||||
                            </div>
 | 
			
		||||
                          </>
 | 
			
		||||
                        )}
 | 
			
		||||
 | 
			
		||||
                        <div
 | 
			
		||||
                          className={styles["chat-message-top-action"]}
 | 
			
		||||
                          onClick={() => copyToClipboard(message.content)}
 | 
			
		||||
                        >
 | 
			
		||||
                          {Locale.Chat.Actions.Copy}
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    )}
 | 
			
		||||
                    <Markdown
 | 
			
		||||
                      content={message.content}
 | 
			
		||||
                      loading={
 | 
			
		||||
@@ -929,14 +912,56 @@ export function Chat() {
 | 
			
		||||
                      parentRef={scrollRef}
 | 
			
		||||
                      defaultShow={i >= messages.length - 10}
 | 
			
		||||
                    />
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {!isUser && !message.preview && (
 | 
			
		||||
                    <div className={styles["chat-message-actions"]}>
 | 
			
		||||
                      <div className={styles["chat-message-action-date"]}>
 | 
			
		||||
                        {message.date.toLocaleString()}
 | 
			
		||||
 | 
			
		||||
                    {showActions && (
 | 
			
		||||
                      <div className={styles["chat-message-actions"]}>
 | 
			
		||||
                        <div
 | 
			
		||||
                          className={styles["chat-input-actions"]}
 | 
			
		||||
                          style={{
 | 
			
		||||
                            marginTop: 10,
 | 
			
		||||
                            marginBottom: 0,
 | 
			
		||||
                          }}
 | 
			
		||||
                        >
 | 
			
		||||
                          {message.streaming ? (
 | 
			
		||||
                            <ChatAction
 | 
			
		||||
                              text={Locale.Chat.Actions.Stop}
 | 
			
		||||
                              icon={<StopIcon />}
 | 
			
		||||
                              onClick={() => onUserStop(message.id ?? i)}
 | 
			
		||||
                            />
 | 
			
		||||
                          ) : (
 | 
			
		||||
                            <>
 | 
			
		||||
                              <ChatAction
 | 
			
		||||
                                text={Locale.Chat.Actions.Delete}
 | 
			
		||||
                                icon={<DeleteIcon />}
 | 
			
		||||
                                onClick={() => onDelete(message.id ?? i)}
 | 
			
		||||
                              />
 | 
			
		||||
 | 
			
		||||
                              <ChatAction
 | 
			
		||||
                                text={Locale.Chat.Actions.Retry}
 | 
			
		||||
                                icon={<ResetIcon />}
 | 
			
		||||
                                onClick={() => onResend(message.id ?? i)}
 | 
			
		||||
                              />
 | 
			
		||||
 | 
			
		||||
                              <ChatAction
 | 
			
		||||
                                text={Locale.Chat.Actions.Pin}
 | 
			
		||||
                                icon={<PinIcon />}
 | 
			
		||||
                                onClick={() => onPinMessage(message)}
 | 
			
		||||
                              />
 | 
			
		||||
                            </>
 | 
			
		||||
                          )}
 | 
			
		||||
                          <ChatAction
 | 
			
		||||
                            text={Locale.Chat.Actions.Copy}
 | 
			
		||||
                            icon={<CopyIcon />}
 | 
			
		||||
                            onClick={() => copyToClipboard(message.content)}
 | 
			
		||||
                          />
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <div className={styles["chat-message-action-date"]}>
 | 
			
		||||
                          {message.date.toLocaleString()}
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  )}
 | 
			
		||||
                    )}
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
              {shouldShowClearContextDivider && <ClearContextDivider />}
 | 
			
		||||
 
 | 
			
		||||
@@ -313,243 +313,6 @@
 | 
			
		||||
  margin-right: 15px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-body {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  padding: 20px;
 | 
			
		||||
  padding-bottom: 40px;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  overscroll-behavior: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-body-title {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
 | 
			
		||||
  &:hover {
 | 
			
		||||
    text-decoration: underline;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
 | 
			
		||||
  &:last-child {
 | 
			
		||||
    animation: slide-in ease 0.3s;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-user {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row-reverse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-container {
 | 
			
		||||
  max-width: var(--message-max-width);
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  align-items: flex-start;
 | 
			
		||||
 | 
			
		||||
  &:hover {
 | 
			
		||||
    .chat-message-top-actions {
 | 
			
		||||
      opacity: 1;
 | 
			
		||||
      transform: translateX(10px);
 | 
			
		||||
      pointer-events: all;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-user > .chat-message-container {
 | 
			
		||||
  align-items: flex-end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-avatar {
 | 
			
		||||
  margin-top: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-status {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  color: #aaa;
 | 
			
		||||
  line-height: 1.5;
 | 
			
		||||
  margin-top: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-item {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
  margin-top: 10px;
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  background-color: rgba(0, 0, 0, 0.05);
 | 
			
		||||
  padding: 10px;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  user-select: text;
 | 
			
		||||
  word-break: break-word;
 | 
			
		||||
  border: var(--border-in-light);
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-top-actions {
 | 
			
		||||
  min-width: 120px;
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 20px;
 | 
			
		||||
  top: -26px;
 | 
			
		||||
  left: 30px;
 | 
			
		||||
  transition: all ease 0.3s;
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row-reverse;
 | 
			
		||||
 | 
			
		||||
  .chat-message-top-action {
 | 
			
		||||
    opacity: 0.5;
 | 
			
		||||
    color: var(--black);
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      opacity: 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:not(:first-child) {
 | 
			
		||||
      margin-right: 10px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-user > .chat-message-container > .chat-message-item {
 | 
			
		||||
  background-color: var(--second);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-actions {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row-reverse;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  padding-top: 5px;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-message-action-date {
 | 
			
		||||
  color: #aaa;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input-panel {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  padding: 20px;
 | 
			
		||||
  padding-top: 10px;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  border-top-left-radius: 10px;
 | 
			
		||||
  border-top-right-radius: 10px;
 | 
			
		||||
  border-top: var(--border-in-light);
 | 
			
		||||
  box-shadow: var(--card-shadow);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin single-line {
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.prompt-hints {
 | 
			
		||||
  min-height: 20px;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  max-height: 50vh;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column-reverse;
 | 
			
		||||
 | 
			
		||||
  background-color: var(--white);
 | 
			
		||||
  border: var(--border-in-light);
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  margin-bottom: 10px;
 | 
			
		||||
  box-shadow: var(--shadow);
 | 
			
		||||
 | 
			
		||||
  .prompt-hint {
 | 
			
		||||
    color: var(--black);
 | 
			
		||||
    padding: 6px 10px;
 | 
			
		||||
    animation: slide-in ease 0.3s;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    transition: all ease 0.3s;
 | 
			
		||||
    border: transparent 1px solid;
 | 
			
		||||
    margin: 4px;
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
 | 
			
		||||
    &:not(:last-child) {
 | 
			
		||||
      margin-top: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .hint-title {
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
      font-weight: bolder;
 | 
			
		||||
 | 
			
		||||
      @include single-line();
 | 
			
		||||
    }
 | 
			
		||||
    .hint-content {
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
 | 
			
		||||
      @include single-line();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &-selected,
 | 
			
		||||
    &:hover {
 | 
			
		||||
      border-color: var(--primary);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input-panel-inner {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  border: var(--border-in-light);
 | 
			
		||||
  box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.03);
 | 
			
		||||
  background-color: var(--white);
 | 
			
		||||
  color: var(--black);
 | 
			
		||||
  font-family: inherit;
 | 
			
		||||
  padding: 10px 90px 10px 14px;
 | 
			
		||||
  resize: none;
 | 
			
		||||
  outline: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input:focus {
 | 
			
		||||
  border: 1px solid var(--primary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-input-send {
 | 
			
		||||
  background-color: var(--primary);
 | 
			
		||||
  color: white;
 | 
			
		||||
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 30px;
 | 
			
		||||
  bottom: 32px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media only screen and (max-width: 600px) {
 | 
			
		||||
  .chat-input {
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .chat-input-send {
 | 
			
		||||
    bottom: 30px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.loading-content {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								app/icons/pin.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								app/icons/pin.svg
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
		 After Width: | Height: | Size: 5.8 KiB  | 
@@ -25,6 +25,9 @@ const cn = {
 | 
			
		||||
      Copy: "复制",
 | 
			
		||||
      Stop: "停止",
 | 
			
		||||
      Retry: "重试",
 | 
			
		||||
      Pin: "固定",
 | 
			
		||||
      PinToastContent: "已将 2 条对话固定至预设提示词",
 | 
			
		||||
      PinToastAction: "查看",
 | 
			
		||||
      Delete: "删除",
 | 
			
		||||
    },
 | 
			
		||||
    Commands: {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,9 @@ const en: LocaleType = {
 | 
			
		||||
      Copy: "Copy",
 | 
			
		||||
      Stop: "Stop",
 | 
			
		||||
      Retry: "Retry",
 | 
			
		||||
      Pin: "Pin",
 | 
			
		||||
      PinToastContent: "Pinned 2 messages to contextual prompts",
 | 
			
		||||
      PinToastAction: "View",
 | 
			
		||||
      Delete: "Delete",
 | 
			
		||||
    },
 | 
			
		||||
    Commands: {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user