feat: use rounded corner design
This commit is contained in:
parent
d7f8eec59e
commit
3d3410b4fd
@ -21,13 +21,13 @@ export const DATA_PATH = getDataPath()
|
|||||||
export const appConfig = new Store()
|
export const appConfig = new Store()
|
||||||
|
|
||||||
export const titleBarOverlayDark = {
|
export const titleBarOverlayDark = {
|
||||||
height: 41,
|
height: 40,
|
||||||
color: '#00000000',
|
color: '#00000000',
|
||||||
symbolColor: '#ffffff'
|
symbolColor: '#ffffff'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const titleBarOverlayLight = {
|
export const titleBarOverlayLight = {
|
||||||
height: 41,
|
height: 40,
|
||||||
color: '#00000000',
|
color: '#00000000',
|
||||||
symbolColor: '#000000'
|
symbolColor: '#000000'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export function createMainWindow() {
|
|||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
transparent: process.platform === 'darwin',
|
transparent: process.platform === 'darwin',
|
||||||
vibrancy: 'fullscreen-ui',
|
vibrancy: 'fullscreen-ui',
|
||||||
|
visualEffectState: 'active',
|
||||||
titleBarStyle: 'hidden',
|
titleBarStyle: 'hidden',
|
||||||
titleBarOverlay: theme === 'dark' ? titleBarOverlayDark : titleBarOverlayLight,
|
titleBarOverlay: theme === 'dark' ? titleBarOverlayDark : titleBarOverlayLight,
|
||||||
trafficLightPosition: { x: 8, y: 12 },
|
trafficLightPosition: { x: 8, y: 12 },
|
||||||
|
|||||||
@ -7,11 +7,19 @@
|
|||||||
http-equiv="Content-Security-Policy"
|
http-equiv="Content-Security-Policy"
|
||||||
content="default-src 'self'; connect-src *; script-src 'self' *; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' *; font-src 'self' data: *; img-src 'self' data: file: *; frame-src * file:" />
|
content="default-src 'self'; connect-src *; script-src 'self' *; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' *; font-src 'self' data: *; img-src 'self' data: file: *; frame-src * file:" />
|
||||||
<style>
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
#spinner {
|
#spinner {
|
||||||
position: absolute;
|
position: fixed;
|
||||||
top: 50%;
|
width: 100vw;
|
||||||
left: 50%;
|
height: 100vh;
|
||||||
transform: translate(-50%, -50%);
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background: rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
#spinner img {
|
#spinner img {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
|
|||||||
@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
--color-white: #ffffff;
|
--color-white: #ffffff;
|
||||||
--color-white-soft: #f8f8f8;
|
--color-white-soft: rgba(255, 255, 255, 0.8);
|
||||||
--color-white-mute: #f2f2f2;
|
--color-white-mute: rgba(255, 255, 255, 0.94);
|
||||||
|
|
||||||
--color-black: #1b1b1f;
|
--color-black: #181818;
|
||||||
--color-black-soft: #262626;
|
--color-black-soft: #202020;
|
||||||
--color-black-mute: #363636;
|
--color-black-mute: #262626;
|
||||||
|
|
||||||
--color-gray-1: #515c67;
|
--color-gray-1: #515c67;
|
||||||
--color-gray-2: #414853;
|
--color-gray-2: #414853;
|
||||||
@ -20,9 +20,9 @@
|
|||||||
--color-text-2: rgba(235, 235, 245, 0.6);
|
--color-text-2: rgba(235, 235, 245, 0.6);
|
||||||
--color-text-3: rgba(235, 235, 245, 0.38);
|
--color-text-3: rgba(235, 235, 245, 0.38);
|
||||||
|
|
||||||
--color-background: #181818;
|
--color-background: var(--color-black);
|
||||||
--color-background-soft: var(--color-black-soft);
|
--color-background-soft: var(--color-black-soft);
|
||||||
--color-background-mute: var(--color-black-soft);
|
--color-background-mute: var(--color-black-mute);
|
||||||
|
|
||||||
--color-primary: #00b96b;
|
--color-primary: #00b96b;
|
||||||
--color-primary-soft: #00b96b99;
|
--color-primary-soft: #00b96b99;
|
||||||
@ -31,32 +31,33 @@
|
|||||||
--color-text: var(--color-text-1);
|
--color-text: var(--color-text-1);
|
||||||
--color-icon: #ffffff99;
|
--color-icon: #ffffff99;
|
||||||
--color-icon-white: #ffffff;
|
--color-icon-white: #ffffff;
|
||||||
--color-border: #ffffff20;
|
--color-border: #ffffff24;
|
||||||
--color-border-soft: #ffffff20;
|
--color-border-soft: #ffffff20;
|
||||||
--color-error: #f44336;
|
--color-error: #f44336;
|
||||||
--color-link: #1677ff;
|
--color-link: #1677ff;
|
||||||
--color-code-background: #323232;
|
--color-code-background: #323232;
|
||||||
--color-scrollbar-thumb: rgba(255, 255, 255, 0.08);
|
--color-scrollbar-thumb: rgba(255, 255, 255, 0.08);
|
||||||
--color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.15);
|
--color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.15);
|
||||||
|
--color-hover: rgba(40, 40, 40, 1);
|
||||||
|
--color-active: rgba(55, 55, 55, 1);
|
||||||
|
|
||||||
--navbar-background-mac: rgba(30, 30, 30, 0.8);
|
--navbar-background-mac: rgba(30, 30, 30, 0.4);
|
||||||
--navbar-background: rgba(30, 30, 30);
|
--navbar-background: rgba(30, 30, 30);
|
||||||
--input-bar-background: rgba(255, 255, 255, 0.02);
|
|
||||||
|
|
||||||
--navbar-height: 42px;
|
--navbar-height: 40px;
|
||||||
--sidebar-width: 52px;
|
--sidebar-width: 50px;
|
||||||
--status-bar-height: 40px;
|
--status-bar-height: 40px;
|
||||||
--input-bar-height: 85px;
|
--input-bar-height: 85px;
|
||||||
|
|
||||||
--assistants-width: 280px;
|
--assistants-width: 275px;
|
||||||
--topic-list-width: 280px;
|
--topic-list-width: 275px;
|
||||||
--settings-width: 260px;
|
--settings-width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme-mode='light'] {
|
body[theme-mode='light'] {
|
||||||
--color-white: #ffffff;
|
--color-white: #ffffff;
|
||||||
--color-white-soft: #f8f8f8;
|
--color-white-soft: #f2f2f2;
|
||||||
--color-white-mute: #efefef;
|
--color-white-mute: #eee;
|
||||||
|
|
||||||
--color-black: #1b1b1f;
|
--color-black: #1b1b1f;
|
||||||
--color-black-soft: #262626;
|
--color-black-soft: #262626;
|
||||||
@ -70,7 +71,7 @@ body[theme-mode='light'] {
|
|||||||
--color-text-2: rgba(0, 0, 0, 0.6);
|
--color-text-2: rgba(0, 0, 0, 0.6);
|
||||||
--color-text-3: rgba(0, 0, 0, 0.38);
|
--color-text-3: rgba(0, 0, 0, 0.38);
|
||||||
|
|
||||||
--color-background: #ffffff;
|
--color-background: var(--color-white);
|
||||||
--color-background-soft: var(--color-white-soft);
|
--color-background-soft: var(--color-white-soft);
|
||||||
--color-background-mute: var(--color-white-mute);
|
--color-background-mute: var(--color-white-mute);
|
||||||
|
|
||||||
@ -88,10 +89,11 @@ body[theme-mode='light'] {
|
|||||||
--color-code-background: #e3e3e3;
|
--color-code-background: #e3e3e3;
|
||||||
--color-scrollbar-thumb: rgba(0, 0, 0, 0.08);
|
--color-scrollbar-thumb: rgba(0, 0, 0, 0.08);
|
||||||
--color-scrollbar-thumb-hover: rgba(0, 0, 0, 0.15);
|
--color-scrollbar-thumb-hover: rgba(0, 0, 0, 0.15);
|
||||||
|
--color-hover: var(--color-white-mute);
|
||||||
|
--color-active: var(--color-white-soft);
|
||||||
|
|
||||||
--navbar-background-mac: rgba(255, 255, 255, 0.75);
|
--navbar-background-mac: rgba(255, 255, 255, 0.4);
|
||||||
--navbar-background: rgba(255, 255, 255);
|
--navbar-background: rgba(255, 255, 255);
|
||||||
--input-bar-background: rgba(0, 0, 0, 0.02);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
@ -121,12 +123,12 @@ body {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: transparent !important;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
|
||||||
'Helvetica Neue', sans-serif;
|
'Helvetica Neue', sans-serif;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
transition: background-color 0.3s linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@ -148,6 +150,28 @@ body,
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#content-container {
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: var(--color-background);
|
||||||
|
border-top: 0.5px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[os='mac'] {
|
||||||
|
#content-container {
|
||||||
|
border-top-left-radius: 10px;
|
||||||
|
border-bottom-left-radius: 10px;
|
||||||
|
border-top-right-radius: 10px;
|
||||||
|
border-left: 0.5px solid var(--color-border);
|
||||||
|
box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body[os='windows'] {
|
||||||
|
#app-sidebar {
|
||||||
|
border-right: 0.5px solid var(--color-border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#inputbar .ant-input {
|
#inputbar .ant-input {
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
@ -189,6 +213,7 @@ body,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.minapp-drawer {
|
.minapp-drawer {
|
||||||
|
max-width: calc(100vw - var(--sidebar-width));
|
||||||
.ant-drawer-content-wrapper {
|
.ant-drawer-content-wrapper {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
@ -196,15 +221,15 @@ body,
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
min-height: calc(var(--navbar-height) + 0.5px);
|
min-height: calc(var(--navbar-height) + 0.5px);
|
||||||
background: var(--navbar-background);
|
|
||||||
width: calc(100vw - var(--sidebar-width));
|
width: calc(100vw - var(--sidebar-width));
|
||||||
border-bottom: 0.5px solid var(--color-border);
|
|
||||||
margin-top: -0.5px;
|
margin-top: -0.5px;
|
||||||
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
.ant-drawer-body {
|
.ant-drawer-body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-top: var(--navbar-height);
|
margin-top: var(--navbar-height);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@extend #content-container;
|
||||||
}
|
}
|
||||||
.minapp-mask {
|
.minapp-mask {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
@ -216,6 +241,9 @@ body,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.segmented-tab {
|
.segmented-tab {
|
||||||
|
.ant-segmented-item-selected {
|
||||||
|
background-color: var(--color-background-mute);
|
||||||
|
}
|
||||||
.ant-segmented-item-label {
|
.ant-segmented-item-label {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -5,9 +5,10 @@ import { useBridge } from '@renderer/hooks/useBridge'
|
|||||||
import store from '@renderer/store'
|
import store from '@renderer/store'
|
||||||
import { setMinappShow } from '@renderer/store/runtime'
|
import { setMinappShow } from '@renderer/store/runtime'
|
||||||
import { MinAppType } from '@renderer/types'
|
import { MinAppType } from '@renderer/types'
|
||||||
import { Drawer } from 'antd'
|
import { Avatar, Drawer } from 'antd'
|
||||||
import { WebviewTag } from 'electron'
|
import { WebviewTag } from 'electron'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
import BeatLoader from 'react-spinners/BeatLoader'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import { TopView } from '../TopView'
|
import { TopView } from '../TopView'
|
||||||
@ -19,6 +20,8 @@ interface Props {
|
|||||||
|
|
||||||
const PopupContainer: React.FC<Props> = ({ app, resolve }) => {
|
const PopupContainer: React.FC<Props> = ({ app, resolve }) => {
|
||||||
const [open, setOpen] = useState(true)
|
const [open, setOpen] = useState(true)
|
||||||
|
const [opened, setOpened] = useState(false)
|
||||||
|
const [isReady, setIsReady] = useState(false)
|
||||||
const webviewRef = useRef<WebviewTag | null>(null)
|
const webviewRef = useRef<WebviewTag | null>(null)
|
||||||
|
|
||||||
useBridge()
|
useBridge()
|
||||||
@ -74,14 +77,22 @@ const PopupContainer: React.FC<Props> = ({ app, resolve }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onLoaded = () => setIsReady(true)
|
||||||
|
|
||||||
webview.addEventListener('new-window', handleNewWindow)
|
webview.addEventListener('new-window', handleNewWindow)
|
||||||
|
webview.addEventListener('did-finish-load', onLoaded)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
webview.removeEventListener('new-window', handleNewWindow)
|
webview.removeEventListener('new-window', handleNewWindow)
|
||||||
|
webview.removeEventListener('did-finish-load', onLoaded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {}
|
return () => {}
|
||||||
|
}, [opened])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTimeout(() => setOpened(true), 350)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -97,7 +108,13 @@ const PopupContainer: React.FC<Props> = ({ app, resolve }) => {
|
|||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
closeIcon={null}
|
closeIcon={null}
|
||||||
style={{ marginLeft: 'var(--sidebar-width)' }}>
|
style={{ marginLeft: 'var(--sidebar-width)' }}>
|
||||||
<webview src={app.url} ref={webviewRef} style={WebviewStyle} allowpopups={'true' as any} />
|
{!isReady && (
|
||||||
|
<EmptyView>
|
||||||
|
<Avatar src={app.logo} size={80} style={{ border: '1px solid var(--color-border)', marginTop: -150 }} />
|
||||||
|
<BeatLoader color="var(--color-text-2)" size="10" style={{ marginTop: 15 }} />
|
||||||
|
</EmptyView>
|
||||||
|
)}
|
||||||
|
{opened && <webview src={app.url} ref={webviewRef} style={WebviewStyle} allowpopups={'true' as any} />}
|
||||||
</Drawer>
|
</Drawer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -163,6 +180,17 @@ const Button = styled.div`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const EmptyView = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--color-background);
|
||||||
|
`
|
||||||
|
|
||||||
export default class MinApp {
|
export default class MinApp {
|
||||||
static topviewId = 0
|
static topviewId = 0
|
||||||
static onClose = () => {}
|
static onClose = () => {}
|
||||||
|
|||||||
@ -99,7 +99,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
autoFocus
|
autoFocus
|
||||||
style={{ paddingLeft: 0 }}
|
style={{ paddingLeft: 0 }}
|
||||||
bordered={false}
|
bordered={false}
|
||||||
size="large"
|
size="middle"
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
<Divider style={{ margin: 0 }} />
|
<Divider style={{ margin: 0 }} />
|
||||||
@ -136,13 +136,13 @@ const AgentItem = styled.div`
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 10px 15px;
|
padding: 8px 15px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&.default {
|
&.default {
|
||||||
background-color: var(--color-background-soft);
|
background-color: var(--color-background-mute);
|
||||||
}
|
}
|
||||||
.anticon {
|
.anticon {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -162,7 +162,7 @@ const SearchIcon = styled.div`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: var(--color-background-soft);
|
background-color: var(--color-background-soft);
|
||||||
margin-right: 6px;
|
margin-right: 2px;
|
||||||
`
|
`
|
||||||
|
|
||||||
export default class AddAssistantPopup {
|
export default class AddAssistantPopup {
|
||||||
|
|||||||
@ -1,18 +1,15 @@
|
|||||||
import { isMac } from '@renderer/config/constant'
|
import { isMac } from '@renderer/config/constant'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import { useRuntime } from '@renderer/hooks/useStore'
|
|
||||||
import { FC, PropsWithChildren } from 'react'
|
import { FC, PropsWithChildren } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
type Props = PropsWithChildren & JSX.IntrinsicElements['div']
|
type Props = PropsWithChildren & JSX.IntrinsicElements['div']
|
||||||
|
|
||||||
export const Navbar: FC<Props> = ({ children, ...props }) => {
|
export const Navbar: FC<Props> = ({ children, ...props }) => {
|
||||||
const { minappShow } = useRuntime()
|
|
||||||
const { windowStyle } = useSettings()
|
const { windowStyle } = useSettings()
|
||||||
|
|
||||||
const macTransparentWindow = isMac && windowStyle === 'transparent'
|
const macTransparentWindow = isMac && windowStyle === 'transparent'
|
||||||
const navbarBgColor = macTransparentWindow ? 'var(--navbar-background-mac)' : 'var(--navbar-background)'
|
const backgroundColor = macTransparentWindow ? 'transparent' : 'var(--navbar-background)'
|
||||||
const backgroundColor = minappShow ? 'var(--navbar-background)' : navbarBgColor
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavbarContainer {...props} style={{ backgroundColor }}>
|
<NavbarContainer {...props} style={{ backgroundColor }}>
|
||||||
@ -41,7 +38,6 @@ const NavbarContainer = styled.div`
|
|||||||
max-height: var(--navbar-height);
|
max-height: var(--navbar-height);
|
||||||
margin-left: ${isMac ? 'calc(var(--sidebar-width) * -1)' : 0};
|
margin-left: ${isMac ? 'calc(var(--sidebar-width) * -1)' : 0};
|
||||||
padding-left: ${isMac ? 'var(--sidebar-width)' : 0};
|
padding-left: ${isMac ? 'var(--sidebar-width)' : 0};
|
||||||
border-bottom: 0.5px solid var(--color-border);
|
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
`
|
`
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const Sidebar: FC = () => {
|
|||||||
const onEditUser = () => UserPopup.show()
|
const onEditUser = () => UserPopup.show()
|
||||||
|
|
||||||
const macTransparentWindow = isMac && windowStyle === 'transparent'
|
const macTransparentWindow = isMac && windowStyle === 'transparent'
|
||||||
const sidebarBgColor = macTransparentWindow ? 'var(--navbar-background-mac)' : 'var(--navbar-background)'
|
const sidebarBgColor = macTransparentWindow ? 'transparent' : 'var(--navbar-background)'
|
||||||
|
|
||||||
const to = (path: string) => {
|
const to = (path: string) => {
|
||||||
if (generating) {
|
if (generating) {
|
||||||
@ -39,8 +39,9 @@ const Sidebar: FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
|
id="app-sidebar"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: minappShow ? 'var(--navbar-background)' : sidebarBgColor,
|
backgroundColor: sidebarBgColor,
|
||||||
zIndex: minappShow ? 10000 : 'initial'
|
zIndex: minappShow ? 10000 : 'initial'
|
||||||
}}>
|
}}>
|
||||||
<AvatarImg src={avatar || UserAvatar} draggable={false} className="nodrag" onClick={onEditUser} />
|
<AvatarImg src={avatar || UserAvatar} draggable={false} className="nodrag" onClick={onEditUser} />
|
||||||
@ -93,7 +94,6 @@ const Container = styled.div`
|
|||||||
min-width: var(--sidebar-width);
|
min-width: var(--sidebar-width);
|
||||||
height: ${isMac ? 'calc(100vh - var(--navbar-height))' : '100vh'};
|
height: ${isMac ? 'calc(100vh - var(--navbar-height))' : '100vh'};
|
||||||
-webkit-app-region: drag !important;
|
-webkit-app-region: drag !important;
|
||||||
border-right: 0.5px solid var(--color-border);
|
|
||||||
margin-top: ${isMac ? 'var(--navbar-height)' : 0};
|
margin-top: ${isMac ? 'var(--navbar-height)' : 0};
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
`
|
`
|
||||||
@ -103,7 +103,7 @@ const AvatarImg = styled(Avatar)`
|
|||||||
height: 32px;
|
height: 32px;
|
||||||
background-color: var(--color-background-soft);
|
background-color: var(--color-background-soft);
|
||||||
margin-bottom: ${isMac ? '12px' : '12px'};
|
margin-bottom: ${isMac ? '12px' : '12px'};
|
||||||
margin-top: ${isMac ? '5px' : '2px'};
|
margin-top: ${isMac ? '-5px' : '2px'};
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`
|
`
|
||||||
@ -140,7 +140,7 @@ const Icon = styled.div`
|
|||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--color-background-soft);
|
background-color: var(--color-hover);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
.iconfont,
|
.iconfont,
|
||||||
.anticon {
|
.anticon {
|
||||||
@ -148,7 +148,7 @@ const Icon = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.active {
|
&.active {
|
||||||
background-color: var(--color-background-mute);
|
background-color: var(--color-active);
|
||||||
.iconfont,
|
.iconfont,
|
||||||
.anticon {
|
.anticon {
|
||||||
color: var(--color-icon-white);
|
color: var(--color-icon-white);
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { isMac } from '@renderer/config/constant'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import { ThemeMode } from '@renderer/types'
|
import { ThemeMode } from '@renderer/types'
|
||||||
import React, { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react'
|
import React, { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react'
|
||||||
@ -37,6 +38,10 @@ export const ThemeProvider: React.FC<PropsWithChildren> = ({ children }) => {
|
|||||||
window.api?.setTheme(_theme === ThemeMode.dark ? 'dark' : 'light')
|
window.api?.setTheme(_theme === ThemeMode.dark ? 'dark' : 'light')
|
||||||
}, [_theme])
|
}, [_theme])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.body.setAttribute('os', isMac ? 'mac' : 'windows')
|
||||||
|
}, [])
|
||||||
|
|
||||||
return <ThemeContext.Provider value={{ theme: _theme, toggleTheme }}>{children}</ThemeContext.Provider>
|
return <ThemeContext.Provider value={{ theme: _theme, toggleTheme }}>{children}</ThemeContext.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { isMac } from '@renderer/config/constant'
|
||||||
import { isLocalAi } from '@renderer/config/env'
|
import { isLocalAi } from '@renderer/config/env'
|
||||||
import db from '@renderer/databases'
|
import db from '@renderer/databases'
|
||||||
import i18n from '@renderer/i18n'
|
import i18n from '@renderer/i18n'
|
||||||
@ -9,10 +10,12 @@ import { useEffect } from 'react'
|
|||||||
|
|
||||||
import { useDefaultModel } from './useAssistant'
|
import { useDefaultModel } from './useAssistant'
|
||||||
import { useSettings } from './useSettings'
|
import { useSettings } from './useSettings'
|
||||||
|
import { useRuntime } from './useStore'
|
||||||
|
|
||||||
export function useAppInit() {
|
export function useAppInit() {
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
const { proxyUrl, language } = useSettings()
|
const { proxyUrl, language, windowStyle } = useSettings()
|
||||||
|
const { minappShow } = useRuntime()
|
||||||
const { setDefaultModel, setTopicNamingModel, setTranslateModel } = useDefaultModel()
|
const { setDefaultModel, setTopicNamingModel, setTranslateModel } = useDefaultModel()
|
||||||
const avatar = useLiveQuery(() => db.settings.get('image://avatar'))
|
const avatar = useLiveQuery(() => db.settings.get('image://avatar'))
|
||||||
|
|
||||||
@ -36,6 +39,13 @@ export function useAppInit() {
|
|||||||
i18n.changeLanguage(language || navigator.language || 'en-US')
|
i18n.changeLanguage(language || navigator.language || 'en-US')
|
||||||
}, [language])
|
}, [language])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const transparentWindow = windowStyle === 'transparent' && isMac && !minappShow
|
||||||
|
window.document.body.style.background = transparentWindow
|
||||||
|
? 'var(--navbar-background-mac)'
|
||||||
|
: 'var(--navbar-background)'
|
||||||
|
}, [windowStyle, minappShow])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLocalAi) {
|
if (isLocalAi) {
|
||||||
const model = JSON.parse(import.meta.env.VITE_RENDERER_INTEGRATED_MODEL)
|
const model = JSON.parse(import.meta.env.VITE_RENDERER_INTEGRATED_MODEL)
|
||||||
|
|||||||
@ -54,7 +54,7 @@ const AppsPage: FC = () => {
|
|||||||
<Navbar>
|
<Navbar>
|
||||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('agents.title')}</NavbarCenter>
|
<NavbarCenter style={{ borderRight: 'none' }}>{t('agents.title')}</NavbarCenter>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<ContentContainer>
|
<ContentContainer id="content-container">
|
||||||
<AssistantsContainer>
|
<AssistantsContainer>
|
||||||
<HStack alignItems="center" style={{ marginBottom: 16 }}>
|
<HStack alignItems="center" style={{ marginBottom: 16 }}>
|
||||||
<Title level={4}>{t('agents.my_agents')}</Title>
|
<Title level={4}>{t('agents.my_agents')}</Title>
|
||||||
@ -98,7 +98,6 @@ const ContentContainer = styled.div`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
background-color: var(--color-background);
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const AssistantsContainer = styled.div`
|
const AssistantsContainer = styled.div`
|
||||||
|
|||||||
@ -39,7 +39,7 @@ const AppsPage: FC = () => {
|
|||||||
<div style={{ width: 80 }} />
|
<div style={{ width: 80 }} />
|
||||||
</NavbarCenter>
|
</NavbarCenter>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<ContentContainer>
|
<ContentContainer id="content-container">
|
||||||
<AppsContainer>
|
<AppsContainer>
|
||||||
{filteredApps.map((app) => (
|
{filteredApps.map((app) => (
|
||||||
<App key={app.id} app={app} />
|
<App key={app.id} app={app} />
|
||||||
@ -69,7 +69,6 @@ const ContentContainer = styled.div`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
background-color: var(--color-background);
|
|
||||||
padding: 50px;
|
padding: 50px;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
@ -64,7 +64,7 @@ const FilesPage: FC = () => {
|
|||||||
<Navbar>
|
<Navbar>
|
||||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('files.title')}</NavbarCenter>
|
<NavbarCenter style={{ borderRight: 'none' }}>{t('files.title')}</NavbarCenter>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<ContentContainer>
|
<ContentContainer id="content-container">
|
||||||
<VStack style={{ flex: 1 }}>
|
<VStack style={{ flex: 1 }}>
|
||||||
<Table dataSource={dataSource} columns={columns} style={{ width: '100%', height: '100%' }} size="small" />
|
<Table dataSource={dataSource} columns={columns} style={{ width: '100%', height: '100%' }} size="small" />
|
||||||
</VStack>
|
</VStack>
|
||||||
@ -87,7 +87,6 @@ const ContentContainer = styled.div`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
background-color: var(--color-background);
|
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,7 @@ const Container = styled.div`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
background-color: var(--color-background);
|
||||||
`
|
`
|
||||||
|
|
||||||
const Main = styled(Flex)`
|
const Main = styled(Flex)`
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const HomePage: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Navbar activeAssistant={activeAssistant} activeTopic={activeTopic} setActiveTopic={setActiveTopic} />
|
<Navbar activeAssistant={activeAssistant} activeTopic={activeTopic} setActiveTopic={setActiveTopic} />
|
||||||
<ContentContainer>
|
<ContentContainer id="content-container">
|
||||||
{showAssistants && (
|
{showAssistants && (
|
||||||
<RightSidebar
|
<RightSidebar
|
||||||
activeAssistant={activeAssistant}
|
activeAssistant={activeAssistant}
|
||||||
@ -53,7 +53,6 @@ const ContentContainer = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
background-color: var(--color-background);
|
|
||||||
`
|
`
|
||||||
|
|
||||||
export default HomePage
|
export default HomePage
|
||||||
|
|||||||
@ -354,8 +354,6 @@ const InputBarContainer = styled.div`
|
|||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 20px 15px 20px;
|
margin: 0 20px 15px 20px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
&.focus {
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const Textarea = styled(TextArea)`
|
const Textarea = styled(TextArea)`
|
||||||
|
|||||||
@ -103,7 +103,7 @@ export const NewButton = styled.div`
|
|||||||
transition: all 0.2s ease-in-out;
|
transition: all 0.2s ease-in-out;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
.iconfont {
|
.iconfont {
|
||||||
font-size: 19px;
|
font-size: 18px;
|
||||||
color: var(--color-icon);
|
color: var(--color-icon);
|
||||||
&.icon-a-addchat {
|
&.icon-a-addchat {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
@ -114,7 +114,7 @@ export const NewButton = styled.div`
|
|||||||
}
|
}
|
||||||
.anticon {
|
.anticon {
|
||||||
color: var(--color-icon);
|
color: var(--color-icon);
|
||||||
font-size: 17px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--color-background-mute);
|
background-color: var(--color-background-mute);
|
||||||
|
|||||||
@ -37,7 +37,8 @@ const RightSidebar: FC<Props> = ({ activeAssistant, activeTopic, setActiveAssist
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const borderStyle = '0.5px solid var(--color-border)'
|
const borderStyle = '0.5px solid var(--color-border)'
|
||||||
const border = position === 'left' ? { borderRight: borderStyle } : { borderLeft: borderStyle }
|
const border =
|
||||||
|
position === 'left' ? { borderRight: borderStyle } : { borderLeft: borderStyle, borderTopLeftRadius: 0 }
|
||||||
|
|
||||||
if (position === 'left' && topicPosition === 'left') {
|
if (position === 'left' && topicPosition === 'left') {
|
||||||
_tab = tab
|
_tab = tab
|
||||||
@ -98,7 +99,13 @@ const RightSidebar: FC<Props> = ({ activeAssistant, activeTopic, setActiveAssist
|
|||||||
<Segmented
|
<Segmented
|
||||||
value={tab}
|
value={tab}
|
||||||
className="segmented-tab"
|
className="segmented-tab"
|
||||||
style={{ borderRadius: 0, padding: '10px', gap: 2, borderBottom: borderStyle }}
|
style={{
|
||||||
|
borderRadius: 0,
|
||||||
|
padding: '10px 0',
|
||||||
|
margin: '0 10px',
|
||||||
|
borderBottom: '0.5px solid var(--color-border)',
|
||||||
|
gap: 2
|
||||||
|
}}
|
||||||
options={
|
options={
|
||||||
[
|
[
|
||||||
position === 'left' && topicPosition === 'left' ? assistantTab : undefined,
|
position === 'left' && topicPosition === 'left' ? assistantTab : undefined,
|
||||||
@ -141,6 +148,7 @@ const Container = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: var(--assistants-width);
|
width: var(--assistants-width);
|
||||||
height: calc(100vh - var(--navbar-height));
|
height: calc(100vh - var(--navbar-height));
|
||||||
|
overflow: hidden;
|
||||||
.collapsed {
|
.collapsed {
|
||||||
width: 0;
|
width: 0;
|
||||||
border-left: none;
|
border-left: none;
|
||||||
|
|||||||
@ -23,7 +23,7 @@ const SettingsPage: FC = () => {
|
|||||||
<Navbar>
|
<Navbar>
|
||||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('settings.title')}</NavbarCenter>
|
<NavbarCenter style={{ borderRight: 'none' }}>{t('settings.title')}</NavbarCenter>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<ContentContainer>
|
<ContentContainer id="content-container">
|
||||||
<SettingMenus>
|
<SettingMenus>
|
||||||
{!isLocalAi && (
|
{!isLocalAi && (
|
||||||
<>
|
<>
|
||||||
@ -84,7 +84,6 @@ const ContentContainer = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
background-color: var(--color-background);
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const SettingMenus = styled.ul`
|
const SettingMenus = styled.ul`
|
||||||
|
|||||||
@ -164,7 +164,7 @@ const TranslatePage: FC = () => {
|
|||||||
<Navbar>
|
<Navbar>
|
||||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('translate.title')}</NavbarCenter>
|
<NavbarCenter style={{ borderRight: 'none' }}>{t('translate.title')}</NavbarCenter>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<ContentContainer>
|
<ContentContainer id="content-container">
|
||||||
<MenuContainer>
|
<MenuContainer>
|
||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
@ -239,7 +239,6 @@ const ContentContainer = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background-color: var(--color-background);
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const MenuContainer = styled.div`
|
const MenuContainer = styled.div`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user