diff --git a/src/renderer/index.html b/src/renderer/index.html index 8c6fbec9..9157450d 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -6,7 +6,7 @@ + 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:; frame-src *" />
diff --git a/src/renderer/src/assets/styles/index.scss b/src/renderer/src/assets/styles/index.scss index 2b1a1901..1a046469 100644 --- a/src/renderer/src/assets/styles/index.scss +++ b/src/renderer/src/assets/styles/index.scss @@ -162,3 +162,40 @@ body, .ant-segmented-group { gap: 4px; } + +.dragable { + -webkit-app-region: drag; +} + +.dragdisable { + -webkit-app-region: no-drag; +} + +.minapp-drawer { + .ant-drawer-header-title { + flex-direction: row-reverse; + } + .ant-drawer-close { + position: absolute; + top: 6px; + right: 15px; + padding: 15px; + margin-right: -5px; + -webkit-app-region: no-drag; + z-index: 100000; + } + .ant-drawer-header { + height: calc(var(--navbar-height) + 0.5px); + background: var(--navbar-background); + width: calc(100vw - var(--sidebar-width)); + padding-right: 10px !important; + border-bottom: 0.5px solid var(--color-border); + margin-top: -0.5px; + } + .ant-drawer-body { + padding: 0; + } + .minapp-mask { + background-color: transparent !important; + } +} diff --git a/src/renderer/src/components/MinApp/index.tsx b/src/renderer/src/components/MinApp/index.tsx new file mode 100644 index 00000000..541931aa --- /dev/null +++ b/src/renderer/src/components/MinApp/index.tsx @@ -0,0 +1,125 @@ +import { CloseOutlined, ExportOutlined, ReloadOutlined } from '@ant-design/icons' +import store from '@renderer/store' +import { setMinappShow } from '@renderer/store/runtime' +import { Drawer } from 'antd' +import { useRef, useState } from 'react' +import styled from 'styled-components' + +import { TopView } from '../TopView' + +interface ShowParams { + title: string + url: string +} + +interface Props extends ShowParams { + resolve: (data: any) => void +} + +const PopupContainer: React.FC = ({ title, url, resolve }) => { + const [open, setOpen] = useState(true) + const iframeRef = useRef(null) + + const onClose = () => { + setOpen(false) + setTimeout(() => resolve({}), 300) + } + + const onReload = () => { + if (iframeRef.current) { + iframeRef.current.src = url + } + } + + const onOpenLink = () => { + window.api.openWebsite(url) + } + + return ( + + + + + + + + + ) +} + +const Frame = styled.iframe` + width: calc(100vw - var(--sidebar-width)); + height: calc(100vh - var(--navbar-height)); + border: none; +` + +const ButtonsGroup = styled.div` + position: absolute; + top: 0; + right: 0; + height: var(--navbar-height); + display: flex; + flex-direction: row; + align-items: center; + gap: 5px; + padding: 0 10px; +` + +const Button = styled.div` + -webkit-app-region: no-drag; + cursor: pointer; + width: 30px; + height: 30px; + border-radius: 5px; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + color: var(--color-text-2); + transition: all 0.2s ease; + font-size: 14px; + &:hover { + color: var(--color-text-1); + background-color: var(--color-background-mute); + } +` + +export default class MinApp { + static topviewId = 0 + static close() { + TopView.hide('MinApp') + store.dispatch(setMinappShow(false)) + } + static start(props: ShowParams) { + store.dispatch(setMinappShow(true)) + return new Promise((resolve) => { + TopView.show( + { + resolve(v) + this.close() + }} + />, + 'MinApp' + ) + }) + } +} diff --git a/src/renderer/src/components/app/Navbar.tsx b/src/renderer/src/components/app/Navbar.tsx index 7a71f85f..c2c62d1a 100644 --- a/src/renderer/src/components/app/Navbar.tsx +++ b/src/renderer/src/components/app/Navbar.tsx @@ -1,11 +1,19 @@ import { isMac } from '@renderer/config/constant' +import { useRuntime } from '@renderer/hooks/useStore' import { FC, PropsWithChildren } from 'react' import styled from 'styled-components' type Props = PropsWithChildren & JSX.IntrinsicElements['div'] export const Navbar: FC = ({ children, ...props }) => { - return {children} + const { minappShow } = useRuntime() + const backgroundColor = minappShow ? 'var(--color-background)' : 'var(--navbar-background)' + + return ( + + {children} + + ) } export const NavbarLeft: FC = ({ children, ...props }) => { @@ -26,11 +34,12 @@ const NavbarContainer = styled.div` flex-direction: row; min-height: var(--navbar-height); max-height: var(--navbar-height); - -webkit-app-region: drag; margin-left: calc(var(--sidebar-width) * -1); padding-left: ${isMac ? 'var(--sidebar-width)' : 0}; border-bottom: 0.5px solid var(--color-border); background-color: var(--navbar-background); + transition: background-color 0.3s ease; + -webkit-app-region: drag; ` const NavbarLeftContainer = styled.div` @@ -56,5 +65,5 @@ const NavbarRightContainer = styled.div` min-width: var(--settings-width); display: flex; align-items: center; - padding: 0 16px; + padding: 0 12px; ` diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx index e683c98a..3295d888 100644 --- a/src/renderer/src/components/app/Sidebar.tsx +++ b/src/renderer/src/components/app/Sidebar.tsx @@ -1,6 +1,7 @@ import { TranslationOutlined } from '@ant-design/icons' import Logo from '@renderer/assets/images/logo.png' import useAvatar from '@renderer/hooks/useAvatar' +import { useRuntime } from '@renderer/hooks/useStore' import { FC } from 'react' import { Link, useLocation } from 'react-router-dom' import styled from 'styled-components' @@ -8,11 +9,12 @@ import styled from 'styled-components' const Sidebar: FC = () => { const { pathname } = useLocation() const avatar = useAvatar() + const { minappShow } = useRuntime() const isRoute = (path: string): string => (pathname === path ? 'active' : '') return ( - + @@ -58,6 +60,7 @@ const Container = styled.div` margin-top: var(--navbar-height); margin-bottom: var(--navbar-height); background-color: var(--sidebar-background); + transition: background-color 0.3s ease; ` const AvatarImg = styled.img` diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx index aa1712ce..b649c2c7 100644 --- a/src/renderer/src/pages/home/HomePage.tsx +++ b/src/renderer/src/pages/home/HomePage.tsx @@ -51,7 +51,7 @@ const HomePage: FC = () => { )} - + } unCheckedChildren={} diff --git a/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx b/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx index 7888cf5b..e2da4dbe 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx @@ -148,7 +148,7 @@ const ProviderSetting: FC = ({ provider: _provider }) => { {t('settings.provider.docs_check')} - {t(`provider.${provider.id}`)} + {t(`provider.${provider.id}`) + ' '} {t('common.docs')} {t('common.and')} diff --git a/src/renderer/src/pages/settings/ProviderSettings/index.tsx b/src/renderer/src/pages/settings/ProviderSettings/index.tsx index ef39c823..acc196ab 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/index.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/index.tsx @@ -167,7 +167,7 @@ const ProviderList = styled.div` flex: 1; flex-direction: column; height: calc(100vh - var(--navbar-height)); - overflow: scroll; + overflow: auto; padding: 8px; ` diff --git a/src/renderer/src/store/runtime.ts b/src/renderer/src/store/runtime.ts index cc01aadb..bfa8ec01 100644 --- a/src/renderer/src/store/runtime.ts +++ b/src/renderer/src/store/runtime.ts @@ -4,11 +4,13 @@ import Logo from '@renderer/assets/images/logo.png' export interface RuntimeState { avatar: string generating: boolean + minappShow: boolean } const initialState: RuntimeState = { avatar: Logo, - generating: false + generating: false, + minappShow: false } const runtimeSlice = createSlice({ @@ -20,10 +22,13 @@ const runtimeSlice = createSlice({ }, setGenerating: (state, action: PayloadAction) => { state.generating = action.payload + }, + setMinappShow: (state, action: PayloadAction) => { + state.minappShow = action.payload } } }) -export const { setAvatar, setGenerating } = runtimeSlice.actions +export const { setAvatar, setGenerating, setMinappShow } = runtimeSlice.actions export default runtimeSlice.reducer