chore: show webview version info in the about window (#869)

This commit is contained in:
Huang Xin
2025-04-12 16:35:54 +08:00
committed by GitHub
parent c807f0ccc8
commit 8f0e2d1642
5 changed files with 90 additions and 12 deletions
@@ -1,9 +1,11 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import Image from 'next/image';
import packageJson from '../../package.json';
import { useEnv } from '@/context/EnvContext';
import { useTranslation } from '@/hooks/useTranslation';
import { hasUpdater } from '@/services/environment';
import { checkForAppUpdates } from '@/helpers/updater';
import { parseWebViewVersion } from '@/utils/ua';
import Dialog from './Dialog';
export const setAboutDialogVisible = (visible: boolean) => {
@@ -17,7 +19,14 @@ export const setAboutDialogVisible = (visible: boolean) => {
export const AboutWindow = () => {
const _ = useTranslation();
const [isUpdated, setIsUpdated] = React.useState(false);
const { appService } = useEnv();
const [isUpdated, setIsUpdated] = useState(false);
const [browserInfo, setBrowserInfo] = useState('');
useEffect(() => {
setBrowserInfo(parseWebViewVersion(appService));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleCheckUpdate = async () => {
const update = await checkForAppUpdates(_, false);
@@ -37,13 +46,15 @@ export const AboutWindow = () => {
>
<div className='about-content flex h-full flex-col items-center justify-center'>
<div className='flex flex-col items-center px-8'>
<div className='mb-4'>
<div className='mb-3'>
<Image src='/icon.png' alt='App Logo' className='h-24 w-24' width={64} height={64} />
</div>
<h2 className='text-2xl font-bold'>Readest</h2>
<p className='text-neutral-content text-sm'>
{_('Version {{version}}', { version: packageJson.version })}
</p>
<div className='flex select-text flex-col items-center'>
<h2 className='text-2xl font-bold'>Readest</h2>
<p className='text-neutral-content text-sm'>
{_('Version {{version}}', { version: packageJson.version })} {`(${browserInfo})`}
</p>
</div>
{hasUpdater() && !isUpdated && (
<span className='badge badge-primary mt-2 cursor-pointer' onClick={handleCheckUpdate}>
{_('Check Update')}
+2 -2
View File
@@ -1,4 +1,4 @@
import { AppPlatform, AppService } from '@/types/system';
import { AppPlatform, AppService, OsPlatform } from '@/types/system';
import { SystemSettings } from '@/types/settings';
import { FileSystem, BaseDir } from '@/types/system';
@@ -41,7 +41,7 @@ import { TxtToEpubConverter } from '@/utils/txt';
import { BOOK_FILE_NOT_FOUND_ERROR } from './errors';
export abstract class BaseAppService implements AppService {
osPlatform: string = getOSPlatform();
osPlatform: OsPlatform = getOSPlatform();
appPlatform: AppPlatform = 'tauri';
localBooksDir = '';
isMobile = false;
+2 -1
View File
@@ -4,6 +4,7 @@ import { BookDoc } from '@/libs/document';
import { ProgressHandler } from '@/utils/transfer';
export type AppPlatform = 'web' | 'tauri';
export type OsPlatform = 'android' | 'ios' | 'macos' | 'windows' | 'linux' | 'unknown';
export type BaseDir = 'Books' | 'Settings' | 'Data' | 'Log' | 'Cache' | 'None';
export interface FileSystem {
@@ -23,7 +24,7 @@ export interface FileSystem {
export interface AppService {
fs: FileSystem;
osPlatform: string;
osPlatform: OsPlatform;
appPlatform: AppPlatform;
hasTrafficLight: boolean;
hasWindow: boolean;
+3 -2
View File
@@ -1,3 +1,4 @@
import { OsPlatform } from '@/types/system';
import { md5 } from 'js-md5';
export const uniqueId = () => Math.random().toString(36).substring(2, 9);
@@ -56,7 +57,7 @@ export const getUserLocale = (lang: string): string | undefined => {
// Note that iPad may have a user agent string like a desktop browser
// when possible please use appService.isIOSApp || getOSPlatform() === 'ios'
// to check if the app is running on iOS
export const getOSPlatform = () => {
export const getOSPlatform = (): OsPlatform => {
const userAgent = navigator.userAgent.toLowerCase();
if (/iphone|ipad|ipod/.test(userAgent)) return 'ios';
@@ -65,7 +66,7 @@ export const getOSPlatform = () => {
if (userAgent.includes('windows nt')) return 'windows';
if (userAgent.includes('linux')) return 'linux';
return '';
return 'unknown';
};
export const isContentURI = (uri: string) => {
+65
View File
@@ -0,0 +1,65 @@
import { AppService } from '@/types/system';
export const parseWebViewVersion = (appService: AppService | null): string => {
const ua = navigator.userAgent;
if (appService?.isAndroidApp) {
// Android WebView
const chromeMatch = ua.match(/Chrome\/([0-9.]+)/);
return chromeMatch ? `WebView ${chromeMatch[1]}` : 'Android WebView';
} else if (appService?.isIOSApp) {
// iOS WebView
const webkitMatch = ua.match(/AppleWebKit\/([0-9.]+)/);
return webkitMatch ? `WebView ${webkitMatch[1]}` : 'iOS WebView';
} else if (appService?.isMacOSApp) {
// macOS WebView
const webkitMatch = ua.match(/AppleWebKit\/([0-9.]+)/);
return webkitMatch ? `WebView ${webkitMatch[1]}` : 'macOS WebView';
} else if (appService?.appPlatform === 'tauri' && appService?.osPlatform === 'windows') {
// Windows WebView2
const match = ua.match(/Edg\/([0-9.]+)/);
return match ? `Edge ${match[1]}` : 'Edge WebView2';
} else if (appService?.appPlatform === 'tauri' && appService?.osPlatform === 'linux') {
// Linux WebView
const match = ua.match(/Chromium\/([0-9.]+)/);
return match ? `WebView ${match[1]}` : 'Linux WebView';
} else if (ua.includes('CriOS') && ua.includes('Mobile/') && ua.includes('Safari')) {
// iOS Chrome WebView
const match = ua.match(/CriOS\/([0-9.]+)/);
return match ? `Chrome ${match[1]}` : 'iOS Chrome';
} else if (ua.includes('FxiOS') && ua.includes('Mobile/') && ua.includes('Safari')) {
// iOS Firefox WebView
const match = ua.match(/FxiOS\/([0-9.]+)/);
return match ? `Firefox ${match[1]}` : 'iOS Firefox';
} else if (ua.includes('Chrome') && ua.includes('AppleWebKit') && ua.includes('Macintosh')) {
// macOS Chrome
const match = ua.match(/Chrome\/([0-9.]+)/);
return match ? `Chrome ${match[1]}` : 'macOS Chrome';
} else if (ua.includes('Safari') && ua.includes('AppleWebKit') && ua.includes('Macintosh')) {
// macOS Safari
const match = ua.match(/Safari\/([0-9.]+)/);
return match ? `Safari ${match[1]}` : 'macOS Safari';
} else if (ua.includes('Edg/')) {
// Microsoft Edge
const match = ua.match(/Edg\/([0-9.]+)/);
return match ? `Edge ${match[1]}` : 'Edge WebView';
} else if (ua.includes('Firefox/')) {
// Firefox
const match = ua.match(/Firefox\/([0-9.]+)/);
return match ? `Firefox ${match[1]}` : 'Firefox Gecko';
} else if (ua.includes('Chrome/') && !ua.includes('Chromium')) {
// Chrome
const match = ua.match(/Chrome\/([0-9.]+)/);
return match ? `Chrome ${match[1]}` : 'Chrome';
} else if (ua.includes('Chromium/')) {
// Chromium
const match = ua.match(/Chromium\/([0-9.]+)/);
return match ? `Chromium ${match[1]}` : 'Chromium';
} else if (ua.includes('MSIE ')) {
// Internet Explorer
const match = ua.match(/MSIE ([0-9.]+)/);
return match ? `IE ${match[1]}` : 'Internet Explorer';
} else {
return 'Unknown';
}
};