forked from akai/readest
chore: show webview version info in the about window (#869)
This commit is contained in:
@@ -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')}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user