mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-26 13:19:34 +07:00
✨ feat(desktop): unify canary with stable app name/icon, add channel tag in About (#12881)
- Use same app name (LobeHub) and icon as stable for canary builds - Add build channel tag in Settings > About for non-stable channels (Canary, Nightly, Beta) - Add getBuildChannel IPC to expose build-time channel for display Made-with: Cursor
This commit is contained in:
@@ -90,8 +90,8 @@ const protocolScheme = getProtocolScheme();
|
||||
|
||||
// Determine icon file based on version type
|
||||
const getIconFileName = () => {
|
||||
if (isStable) return 'Icon';
|
||||
// nightly, canary share pre-release icon
|
||||
if (isStable || isCanary) return 'Icon';
|
||||
// nightly uses pre-release icon
|
||||
return 'Icon-nightly';
|
||||
};
|
||||
|
||||
|
||||
@@ -49,6 +49,16 @@ export default class UpdaterCtr extends ControllerModule {
|
||||
return this.app.storeManager.get('updateChannel') ?? 'stable';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the build-time channel (stable, nightly, canary, beta).
|
||||
* Used for display in About page to distinguish pre-release builds.
|
||||
*/
|
||||
@IpcMethod()
|
||||
async getBuildChannel(): Promise<string> {
|
||||
const { BUILD_CHANNEL } = await import('@/modules/updater/configs');
|
||||
return BUILD_CHANNEL;
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
async setUpdateChannel(channel: UpdateChannel): Promise<void> {
|
||||
const validChannels = new Set(['stable', 'nightly', 'canary']);
|
||||
|
||||
@@ -6,6 +6,8 @@ import { getDesktopEnv } from '@/env';
|
||||
// Build-time default channel, can be overridden at runtime via store
|
||||
const rawChannel = getDesktopEnv().UPDATE_CHANNEL || 'stable';
|
||||
const VALID_CHANNELS = new Set<UpdateChannel>(['stable', 'nightly', 'canary']);
|
||||
/** Raw build channel for display (stable, nightly, canary, beta) */
|
||||
export const BUILD_CHANNEL: string = rawChannel;
|
||||
export const UPDATE_CHANNEL: UpdateChannel = VALID_CHANNELS.has(rawChannel as UpdateChannel)
|
||||
? (rawChannel as UpdateChannel)
|
||||
: rawChannel === 'beta'
|
||||
|
||||
@@ -700,6 +700,7 @@
|
||||
"tab.all": "全部",
|
||||
"tab.apikey": "API Key 管理",
|
||||
"tab.beta": "Beta",
|
||||
"tab.beta.updateChannel.beta": "Beta",
|
||||
"tab.beta.updateChannel.canary": "Canary",
|
||||
"tab.beta.updateChannel.canaryDesc": "每次 PR 合并触发构建,一天可能多次。最不稳定。",
|
||||
"tab.beta.updateChannel.desc": "默认接收稳定版更新通知。Nightly 和 Canary 通道将接收预发布版本,可能不适合生产使用。",
|
||||
|
||||
@@ -96,10 +96,9 @@ function updatePackageJson() {
|
||||
break;
|
||||
}
|
||||
case 'canary': {
|
||||
packageJson.productName = 'LobeHub-Canary';
|
||||
packageJson.productName = 'LobeHub';
|
||||
packageJson.name = 'lobehub-desktop-canary';
|
||||
console.log('🐤 Setting as Canary version.');
|
||||
updateAppIcon('nightly');
|
||||
console.log('🐤 Setting as Canary version (same app name and icon as stable).');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -802,6 +802,7 @@ When I am ___, I need ___
|
||||
'tab.advanced': 'Advanced',
|
||||
'tab.addAgentSkill': 'Add Agent Skill',
|
||||
'tab.beta': 'Beta',
|
||||
'tab.beta.updateChannel.beta': 'Beta',
|
||||
'tab.beta.updateChannel.canary': 'Canary',
|
||||
'tab.beta.updateChannel.canaryDesc':
|
||||
'Triggered on every PR merge, multiple builds per day. Most unstable.',
|
||||
|
||||
@@ -29,7 +29,7 @@ const Version = memo<{ mobile?: boolean }>(({ mobile }) => {
|
||||
s.serverVersion,
|
||||
s.useCheckServerVersion,
|
||||
]);
|
||||
const { t } = useTranslation('common');
|
||||
const { t } = useTranslation(['common', 'setting']);
|
||||
|
||||
useCheckServerVersion();
|
||||
|
||||
@@ -37,12 +37,18 @@ const Version = memo<{ mobile?: boolean }>(({ mobile }) => {
|
||||
const isDesktop = useMemo(() => !!getElectronIpc(), []);
|
||||
|
||||
const [updaterState, setUpdaterState] = useState<UpdaterState>({ stage: 'idle' });
|
||||
const [buildChannel, setBuildChannel] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDesktop) return;
|
||||
autoUpdateService.getUpdaterState().then(setUpdaterState);
|
||||
}, [isDesktop]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDesktop) return;
|
||||
autoUpdateService.getBuildChannel().then(setBuildChannel);
|
||||
}, [isDesktop]);
|
||||
|
||||
useWatchBroadcast('updaterStateChanged', (state: UpdaterState) => {
|
||||
setUpdaterState(state);
|
||||
});
|
||||
@@ -128,6 +134,14 @@ const Version = memo<{ mobile?: boolean }>(({ mobile }) => {
|
||||
<div style={{ fontSize: 18, fontWeight: 'bolder' }}>{BRANDING_NAME}</div>
|
||||
<Flexbox gap={6} horizontal={!mobile}>
|
||||
<Tag>v{CURRENT_VERSION}</Tag>
|
||||
|
||||
{buildChannel && buildChannel !== 'stable' && (
|
||||
<Tag color={'gold'}>
|
||||
{t(`setting:tab.beta.updateChannel.${buildChannel}`, {
|
||||
defaultValue: buildChannel.charAt(0).toUpperCase() + buildChannel.slice(1),
|
||||
})}
|
||||
</Tag>
|
||||
)}
|
||||
{showServerVersion && (
|
||||
<Tag>{t('upgradeVersion.serverVersion', { version: `v${serverVersion}` })}</Tag>
|
||||
)}
|
||||
|
||||
@@ -23,6 +23,10 @@ class AutoUpdateService {
|
||||
return ensureElectronIpc().autoUpdate.getUpdateChannel();
|
||||
};
|
||||
|
||||
getBuildChannel = async (): Promise<string> => {
|
||||
return ensureElectronIpc().autoUpdate.getBuildChannel();
|
||||
};
|
||||
|
||||
setUpdateChannel = async (channel: UpdateChannel): Promise<void> => {
|
||||
return ensureElectronIpc().autoUpdate.setUpdateChannel(channel);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user