diff --git a/CHANGELOG.md b/CHANGELOG.md index c9d5f2342f52..1c60d7530d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ # Changelog +### [Version 1.19.21](https://github.com/lobehub/lobe-chat/compare/v1.19.20...v1.19.21) + +Released on **2024-09-21** + +#### ♻ Code Refactoring + +- **misc**: Refactor to improve branding customization. + +
+ +
+Improvements and Fixes + +#### Code refactoring + +- **misc**: Refactor to improve branding customization, closes [#4061](https://github.com/lobehub/lobe-chat/issues/4061) ([6199e68](https://github.com/lobehub/lobe-chat/commit/6199e68)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ ### [Version 1.19.20](https://github.com/lobehub/lobe-chat/compare/v1.19.19...v1.19.20) Released on **2024-09-21** diff --git a/package.json b/package.json index 289fb210910b..50d48ce49542 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lobehub/chat", - "version": "1.19.20", + "version": "1.19.21", "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.", "keywords": [ "framework", diff --git a/src/app/(main)/chat/features/PageTitle/index.tsx b/src/app/(main)/chat/features/PageTitle/index.tsx index bdda3f39ba40..855e93cb718d 100644 --- a/src/app/(main)/chat/features/PageTitle/index.tsx +++ b/src/app/(main)/chat/features/PageTitle/index.tsx @@ -3,15 +3,16 @@ import { memo } from 'react'; import PageTitle from '@/components/PageTitle'; +import { useChatStore } from '@/store/chat'; +import { topicSelectors } from '@/store/chat/selectors'; import { useSessionStore } from '@/store/session'; import { sessionMetaSelectors } from '@/store/session/selectors'; const Title = memo(() => { - const [avatar, title] = useSessionStore((s) => [ - sessionMetaSelectors.currentAgentAvatar(s), - sessionMetaSelectors.currentAgentTitle(s), - ]); + const agentTitle = useSessionStore(sessionMetaSelectors.currentAgentTitle); - return ; + const topicTitle = useChatStore((s) => topicSelectors.currentActiveTopic(s)?.title); + return ; }); + export default Title; diff --git a/src/app/(main)/welcome/_layout/Desktop.tsx b/src/app/(main)/welcome/_layout/Desktop.tsx index bb6d48d8cf1d..8c1c4796c693 100644 --- a/src/app/(main)/welcome/_layout/Desktop.tsx +++ b/src/app/(main)/welcome/_layout/Desktop.tsx @@ -1,11 +1,12 @@ import { GridShowcase } from '@lobehub/ui'; -import { LobeHub } from '@lobehub/ui/brand'; import { PropsWithChildren } from 'react'; import { Flexbox } from 'react-layout-kit'; +import { ORG_NAME } from '@/const/branding'; +import { isCustomORG } from '@/const/version'; import Follow from '@/features/Follow'; -const COPYRIGHT = `© ${new Date().getFullYear()} LobeHub, LLC`; +const COPYRIGHT = `© ${new Date().getFullYear()} ${ORG_NAME}`; const DesktopLayout = ({ children }: PropsWithChildren) => { return ( @@ -18,7 +19,7 @@ const DesktopLayout = ({ children }: PropsWithChildren) => { style={{ overflow: 'hidden', position: 'relative' }} width={'100%'} > - +
{ {COPYRIGHT} - + {isCustomORG ?
: } {/* ↓ cloud slot ↓ */} diff --git a/src/app/(main)/welcome/page.tsx b/src/app/(main)/welcome/page.tsx index 54993ca16df2..6d45b3bca5f7 100644 --- a/src/app/(main)/welcome/page.tsx +++ b/src/app/(main)/welcome/page.tsx @@ -1,3 +1,4 @@ +import { WelcomeLogo } from '@/components/Branding'; import StructuredData from '@/components/StructuredData'; import { BRANDING_NAME } from '@/const/branding'; import { ldModule } from '@/server/ld'; @@ -7,7 +8,6 @@ import { isMobileDevice } from '@/utils/responsive'; import Actions from './features/Actions'; import Hero from './features/Hero'; -import Logo from './features/Logo'; export const generateMetadata = async () => { const { t } = await translation('metadata'); @@ -30,7 +30,7 @@ const Page = async () => { return ( <> - + diff --git a/src/components/BrandWatermark/index.tsx b/src/components/BrandWatermark/index.tsx index 98aa626d7d12..d650c354e851 100644 --- a/src/components/BrandWatermark/index.tsx +++ b/src/components/BrandWatermark/index.tsx @@ -6,11 +6,13 @@ import Link from 'next/link'; import { memo } from 'react'; import { Flexbox, FlexboxProps } from 'react-layout-kit'; +import { ORG_NAME } from '@/const/branding'; import { UTM_SOURCE } from '@/const/url'; +import { isCustomORG } from '@/const/version'; const useStyles = createStyles(({ token, css }) => ({ logoLink: css` - height: 20px; + line-height: 1; color: inherit; &:hover { @@ -31,13 +33,17 @@ const BrandWatermark = memo>(({ style, ...rest }) {...rest} > Powered by - - - + {isCustomORG ? ( + {ORG_NAME} + ) : ( + + + + )} ); }); diff --git a/src/components/Branding/OrgBrand/index.tsx b/src/components/Branding/OrgBrand/index.tsx new file mode 100644 index 000000000000..5149833a60a5 --- /dev/null +++ b/src/components/Branding/OrgBrand/index.tsx @@ -0,0 +1,13 @@ +import { LobeHub, type LobeHubProps } from '@lobehub/ui/brand'; +import { memo } from 'react'; + +import { ORG_NAME } from '@/const/branding'; +import { isCustomORG } from '@/const/version'; + +export const OrgBrand = memo((props) => { + if (isCustomORG) { + return {ORG_NAME}; + } + + return ; +}); diff --git a/src/components/Branding/CustomLogo.tsx b/src/components/Branding/ProductLogo/Custom.tsx similarity index 100% rename from src/components/Branding/CustomLogo.tsx rename to src/components/Branding/ProductLogo/Custom.tsx diff --git a/src/components/Branding/index.tsx b/src/components/Branding/ProductLogo/index.tsx similarity index 88% rename from src/components/Branding/index.tsx rename to src/components/Branding/ProductLogo/index.tsx index 4e6a64f42a1f..65f88b6a7558 100644 --- a/src/components/Branding/index.tsx +++ b/src/components/Branding/ProductLogo/index.tsx @@ -3,7 +3,7 @@ import { memo } from 'react'; import { isCustomBranding } from '@/const/version'; -import CustomLogo from './CustomLogo'; +import CustomLogo from './Custom'; export const ProductLogo = memo((props) => { if (isCustomBranding) { diff --git a/src/components/Branding/WelcomeLogo/Custom.tsx b/src/components/Branding/WelcomeLogo/Custom.tsx new file mode 100644 index 000000000000..deb0b7a851fd --- /dev/null +++ b/src/components/Branding/WelcomeLogo/Custom.tsx @@ -0,0 +1,41 @@ +'use client'; + +import Image from 'next/image'; +import { memo } from 'react'; +import { Center } from 'react-layout-kit'; + +import { BRANDING_LOGO_URL, BRANDING_NAME } from '@/const/branding'; + +const WelcomeLogo = memo<{ mobile?: boolean }>(({ mobile }) => { + return mobile ? ( +
+ {BRANDING_NAME} +
+ ) : ( +
+ {BRANDING_NAME} +
+ ); +}); + +export default WelcomeLogo; diff --git a/src/app/(main)/welcome/features/Logo.tsx b/src/components/Branding/WelcomeLogo/LobeChat.tsx similarity index 88% rename from src/app/(main)/welcome/features/Logo.tsx rename to src/components/Branding/WelcomeLogo/LobeChat.tsx index 55c8e2a09b1d..a3a9f1831270 100644 --- a/src/app/(main)/welcome/features/Logo.tsx +++ b/src/components/Branding/WelcomeLogo/LobeChat.tsx @@ -7,7 +7,7 @@ import { Center } from 'react-layout-kit'; const LogoThree = dynamic(() => import('@lobehub/ui/es/LogoThree'), { ssr: false }); const LogoSpline = dynamic(() => import('@lobehub/ui/es/LogoThree/LogoSpline'), { ssr: false }); -const Logo = memo<{ mobile?: boolean }>(({ mobile }) => { +const WelcomeLogo = memo<{ mobile?: boolean }>(({ mobile }) => { return mobile ? (
@@ -27,4 +27,4 @@ const Logo = memo<{ mobile?: boolean }>(({ mobile }) => { ); }); -export default Logo; +export default WelcomeLogo; diff --git a/src/components/Branding/WelcomeLogo/index.tsx b/src/components/Branding/WelcomeLogo/index.tsx new file mode 100644 index 000000000000..88436355448c --- /dev/null +++ b/src/components/Branding/WelcomeLogo/index.tsx @@ -0,0 +1,16 @@ +'use client'; + +import { memo } from 'react'; + +import { isCustomBranding } from '@/const/version'; + +import CustomLogo from './Custom'; +import LobeChat from './LobeChat'; + +export const WelcomeLogo = memo<{ mobile?: boolean }>(({ mobile }) => { + if (isCustomBranding) { + return ; + } + + return ; +}); diff --git a/src/components/Branding/index.ts b/src/components/Branding/index.ts new file mode 100644 index 000000000000..3053b0b75ec4 --- /dev/null +++ b/src/components/Branding/index.ts @@ -0,0 +1,3 @@ +export { OrgBrand } from './OrgBrand'; +export { ProductLogo } from './ProductLogo'; +export { WelcomeLogo } from './WelcomeLogo'; diff --git a/src/config/app.ts b/src/config/app.ts index 27e86ab861e0..f088c2ed4ecc 100644 --- a/src/config/app.ts +++ b/src/config/app.ts @@ -43,6 +43,7 @@ export const getAppConfig = () => { PLUGIN_SETTINGS: z.string().optional(), APP_URL: z.string().optional(), + CDN_USE_GLOBAL: z.boolean().optional(), }, runtimeEnv: { NEXT_PUBLIC_BASE_PATH: process.env.NEXT_PUBLIC_BASE_PATH || '', @@ -64,7 +65,10 @@ export const getAppConfig = () => { : 'https://chat-plugins.lobehub.com', PLUGIN_SETTINGS: process.env.PLUGIN_SETTINGS, + APP_URL, + + CDN_USE_GLOBAL: process.env.CDN_USE_GLOBAL === '1', }, }); }; diff --git a/src/const/branding.ts b/src/const/branding.ts index 0c84e84fea21..33d29729af27 100644 --- a/src/const/branding.ts +++ b/src/const/branding.ts @@ -1,8 +1,10 @@ -export const LOBE_CHAT_CLOUD = 'LobeChat Cloud'; - // the code below can only be modified with commercial license // if you want to use it in the commercial usage // please contact us for more information: hello@lobehub.com +export const LOBE_CHAT_CLOUD = 'LobeChat Cloud'; + export const BRANDING_NAME = 'LobeChat'; export const BRANDING_LOGO_URL = ''; + +export const ORG_NAME = 'LobeHub'; diff --git a/src/const/meta.ts b/src/const/meta.ts index 40ef14f0d9c5..4a6d7cc55b05 100644 --- a/src/const/meta.ts +++ b/src/const/meta.ts @@ -5,5 +5,5 @@ export const DEFAULT_AVATAR = '🤖'; export const DEFAULT_USER_AVATAR = '😀'; export const DEFAULT_BACKGROUND_COLOR = 'rgba(0,0,0,0)'; export const DEFAULT_AGENT_META: MetaData = {}; -export const DEFAULT_INBOX_AVATAR = '🤯'; +export const DEFAULT_INBOX_AVATAR = BRANDING_LOGO_URL || '🤯'; export const DEFAULT_USER_AVATAR_URL = BRANDING_LOGO_URL || '/icons/icon-192x192.png'; diff --git a/src/const/version.ts b/src/const/version.ts index 3834e4249504..63ee1d72362a 100644 --- a/src/const/version.ts +++ b/src/const/version.ts @@ -1,7 +1,7 @@ import pkg from '@/../package.json'; import { getServerDBConfig } from '@/config/db'; -import { BRANDING_NAME } from './branding'; +import { BRANDING_NAME, ORG_NAME } from './branding'; export const CURRENT_VERSION = pkg.version; @@ -9,3 +9,5 @@ export const isServerMode = getServerDBConfig().NEXT_PUBLIC_ENABLED_SERVER_SERVI // @ts-ignore export const isCustomBranding = BRANDING_NAME !== 'LobeChat'; +// @ts-ignore +export const isCustomORG = ORG_NAME !== 'LobeHub'; diff --git a/src/layout/GlobalProvider/AppTheme.tsx b/src/layout/GlobalProvider/AppTheme.tsx index f86aa52cdcf7..7b3da5a7e0f2 100644 --- a/src/layout/GlobalProvider/AppTheme.tsx +++ b/src/layout/GlobalProvider/AppTheme.tsx @@ -79,10 +79,11 @@ export interface AppThemeProps { defaultAppearance?: ThemeAppearance; defaultNeutralColor?: NeutralColors; defaultPrimaryColor?: PrimaryColors; + globalCDN?: boolean; } const AppTheme = memo( - ({ children, defaultAppearance, defaultPrimaryColor, defaultNeutralColor }) => { + ({ children, defaultAppearance, defaultPrimaryColor, defaultNeutralColor, globalCDN }) => { // console.debug('server:appearance', defaultAppearance); // console.debug('server:primaryColor', defaultPrimaryColor); // console.debug('server:neutralColor', defaultNeutralColor); @@ -116,7 +117,14 @@ const AppTheme = memo( > - + {children} diff --git a/src/layout/GlobalProvider/index.tsx b/src/layout/GlobalProvider/index.tsx index 92398cc7147a..0dd1535b1a03 100644 --- a/src/layout/GlobalProvider/index.tsx +++ b/src/layout/GlobalProvider/index.tsx @@ -3,6 +3,7 @@ import { cookies, headers } from 'next/headers'; import { FC, PropsWithChildren } from 'react'; import { resolveAcceptLanguage } from 'resolve-accept-language'; +import { appEnv } from '@/config/app'; import { getDebugConfig } from '@/config/debug'; import { getServerFeatureFlagsValue } from '@/config/featureFlags'; import { LOBE_LOCALE_COOKIE } from '@/const/locale'; @@ -82,6 +83,7 @@ const GlobalLayout = async ({ children }: PropsWithChildren) => { defaultAppearance={appearance?.value} defaultNeutralColor={neutralColor?.value as any} defaultPrimaryColor={primaryColor?.value as any} + globalCDN={appEnv.CDN_USE_GLOBAL} >