Skip to content

Commit

Permalink
update scroll action and quota store
Browse files Browse the repository at this point in the history
  • Loading branch information
zmh-program committed Sep 7, 2023
1 parent 8958afc commit cf81373
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 6 deletions.
1 change: 1 addition & 0 deletions api/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func ImageChat(conn *websocket.Conn, instance *conversation.Conversation, user *

markdown := GetImageMarkdown(url)
SendSegmentMessage(conn, types.ChatGPTSegmentResponse{
Quota: 1.,
Message: markdown,
End: true,
})
Expand Down
16 changes: 16 additions & 0 deletions app/src/assets/chat.less
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@
}
}

.scroll-action {
position: absolute;
bottom: 112px;
right: 36px;
opacity: 0;
transition: .25s;

button {
border-color: rgba(0,0,0,0) !important;
}

&.active {
opacity: 0.8;
}
}

.message {
display: flex;
gap: 6px;
Expand Down
45 changes: 39 additions & 6 deletions app/src/routes/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import "../assets/chat.less";
import { Input } from "../components/ui/input.tsx";
import { Toggle } from "../components/ui/toggle.tsx";
import {
ChevronDown,
Globe,
LogIn,
MessageSquare,
Expand All @@ -28,7 +29,7 @@ import {
toggleConversation,
updateConversationList,
} from "../conversation/history.ts";
import React, { useEffect, useRef } from "react";
import React, {useEffect, useRef, useState} from "react";
import { useAnimation, useEffectAsync } from "../utils.ts";
import { useToast } from "../components/ui/use-toast.ts";
import { ConversationInstance, Message } from "../conversation/types.ts";
Expand Down Expand Up @@ -177,23 +178,55 @@ function SideBar() {

function ChatInterface() {
const ref = useRef(null);
const [ scroll, setScroll ] = useState(false);
const messages: Message[] = useSelector(selectMessages);

function listenScrolling() {
if (!ref.current) return;
const el = ref.current as HTMLDivElement;
const offset = el.scrollHeight - el.scrollTop - el.clientHeight;
setScroll(offset > 100);
}

useEffect(
function () {
if (!ref.current) return;
const el = ref.current as HTMLDivElement;
el.scrollTop = el.scrollHeight;
listenScrolling();
},
[messages],
);

useEffect(() => {
if (!ref.current) return;
const el = ref.current as HTMLDivElement;
el.addEventListener('scroll', listenScrolling);
}, [ref]);

return (
<div className={`chat-content`} ref={ref}>
{messages.map((message, i) => (
<MessageSegment message={message} key={i} />
))}
</div>
<>
<div className={`chat-content`} ref={ref}>
<div className={`scroll-action ${scroll ? "active" : ""}`}>
<Button variant={`outline`} size={`icon`} onClick={() => {
if (!ref.current) return;
const el = ref.current as HTMLDivElement;
el.scrollTo({
top: el.scrollHeight,
behavior: 'smooth',
});
}}>
<ChevronDown className={`h-4 w-4`} />
</Button>
</div>

{
messages.map((message, i) =>
<MessageSegment message={message} key={i} />
)
}
</div>
</>
);
}

Expand Down
2 changes: 2 additions & 0 deletions app/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { configureStore } from "@reduxjs/toolkit";
import menuReducer from "./menu";
import authReducer from "./auth";
import chatReducer from "./chat";
import quotaReducer from "./quota";

const store = configureStore({
reducer: {
menu: menuReducer,
auth: authReducer,
chat: chatReducer,
quota: quotaReducer,
},
});

Expand Down
38 changes: 38 additions & 0 deletions app/src/store/quota.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createSlice } from "@reduxjs/toolkit";
import {RootState} from "./index.ts";

export const quotaSlice = createSlice({
name: "quota",
initialState: {
dialog: false,
quota: 0.,
},
reducers: {
toggleDialog: (state) => {
state.dialog = !state.dialog;
},
setDialog: (state, action) => {
state.dialog = action.payload as boolean;
},
closeDialog: (state) => {
state.dialog = false;
},
setQuota: (state, action) => {
state.quota = action.payload as number;
},
increaseQuota: (state, action) => {
state.quota += action.payload as number;
},
decreaseQuota: (state, action) => {
state.quota -= action.payload as number;
},
},
});

export const { toggleDialog, setDialog, closeDialog, setQuota, increaseQuota, decreaseQuota } = quotaSlice.actions;
export default quotaSlice.reducer;

export const dialogSelector = (state: RootState): boolean => state.quota.dialog;
export const quotaValueSelector = (state: RootState): number => state.quota.quota;
export const quotaSelector = (state: RootState): string => state.quota.quota.toFixed(2);

2 changes: 2 additions & 0 deletions middleware/cors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ func CORSMiddleware() gin.HandlerFunc {
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Max-Age", "7200")

if c.Request.Method == "OPTIONS" {
c.Writer.Header().Set("Access-Control-Max-Age", "3600")
Expand Down

0 comments on commit cf81373

Please sign in to comment.