Skip to content

Commit

Permalink
feat(UpdateChecker): 添加最新版本检查功能并优化更新提示
Browse files Browse the repository at this point in the history
  • Loading branch information
thoulee21 committed Nov 24, 2024
1 parent be48fb8 commit 13efa81
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 113 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ android {
applicationId 'com.thoulee.jointplayer'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 5010004
versionName "5.10.4"
versionCode 5011000
versionName "5.11.0"
}
signingConfigs {
debug {
Expand Down
4 changes: 2 additions & 2 deletions ios/jointplayer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 5010004;
CURRENT_PROJECT_VERSION = 5011000;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = jointplayer/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -507,7 +507,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 5010004;
CURRENT_PROJECT_VERSION = 5011000;
INFOPLIST_FILE = jointplayer/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down
4 changes: 2 additions & 2 deletions ios/jointplayer/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>5.10.4</string>
<string>5.11.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5010004</string>
<string>5011000</string>
<key>LSRequiresIPhoneOS</key>
<true />
<key>NSAppTransportSecurity</key>
Expand Down
4 changes: 2 additions & 2 deletions ios/jointplayerTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>5.10.4</string>
<string>5.11.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5010004</string>
<string>5011000</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jointplayer",
"version": "5.10.4",
"version": "5.11.0",
"private": true,
"homepage": "https://github.com/thoulee21/joint-player",
"displayName": "Joint Player",
Expand Down
230 changes: 126 additions & 104 deletions src/components/UpdateChecker.tsx
Original file line number Diff line number Diff line change
@@ -1,128 +1,150 @@
import * as Updates from 'expo-updates';
import React, { useCallback } from 'react';
import { Alert, ToastAndroid } from 'react-native';
import { Alert, Linking, ToastAndroid } from 'react-native';
import HapticFeedback, { HapticFeedbackTypes } from 'react-native-haptic-feedback';
import { ActivityIndicator, List, useTheme } from 'react-native-paper';
import RNRestart from 'react-native-restart';
import useSWR from 'swr';
import packageData from '../../package.json';
import { useAppSelector } from '../hook';
import { selectDevModeEnabled } from '../redux/slices';
import type { Main } from '../types/latestRelease';

export const UpdateChecker = () => {
const appTheme = useTheme();
const isDev = useAppSelector(selectDevModeEnabled);
const appTheme = useTheme();
const isDev = useAppSelector(selectDevModeEnabled);

const {
currentlyRunning,
isUpdatePending,
isChecking,
isDownloading,
lastCheckForUpdateTimeSinceRestart: lastCheck,
availableUpdate,
} = Updates.useUpdates();
const userRepo = packageData.homepage.split('/').slice(-2).join('/');
const { data } = useSWR<Main>(`https://api.github.com/repos/${userRepo}/releases/latest`);
const latestRelease = data?.tag_name;
const isLatest = latestRelease === packageData.version;

const showCurrent = useCallback(() => {
if (isDev) {
HapticFeedback.trigger(HapticFeedbackTypes.effectClick);
if (availableUpdate) {
Alert.alert(
'Available update info',
JSON.stringify(availableUpdate, null, 2)
);
} else {
Alert.alert(
'Current update info',
JSON.stringify(currentlyRunning, null, 2)
);
}
}
}, [availableUpdate, currentlyRunning, isDev]);

const fetchUpdateAndRestart = async () => {
try {
await Updates.fetchUpdateAsync();
RNRestart.Restart();
} catch (err) {
ToastAndroid.show(
`Error updating app: ${JSON.stringify(err)}`,
ToastAndroid.LONG
);
}
};
const {
currentlyRunning,
isUpdatePending,
isChecking,
isDownloading,
lastCheckForUpdateTimeSinceRestart: lastCheck,
availableUpdate,
} = Updates.useUpdates();

const performUpdateAlert = useCallback(() => {
const showCurrent = useCallback(() => {
if (isDev) {
HapticFeedback.trigger(HapticFeedbackTypes.effectClick);
if (availableUpdate) {
Alert.alert(
availableUpdate?.createdAt
? `New update available:\n${availableUpdate?.createdAt.toLocaleString()}`
: 'New update available',
'Do you want to update now?',
[
{ text: 'Cancel' },
{
text: 'OK',
onPress: isUpdatePending
? () => RNRestart.Restart()
: fetchUpdateAndRestart,
},
]
'Available update info',
JSON.stringify(availableUpdate, null, 2)
);
}, [availableUpdate?.createdAt, isUpdatePending]);
} else {
Alert.alert(
'Current update info',
JSON.stringify(currentlyRunning, null, 2)
);
}
}
}, [availableUpdate, currentlyRunning, isDev]);

const checkForUpdate = async () => {
try {
const updateCheckRes = await Updates.checkForUpdateAsync();
const fetchUpdateAndRestart = async () => {
try {
await Updates.fetchUpdateAsync();
RNRestart.Restart();
} catch (err) {
ToastAndroid.show(
`Error updating app: ${JSON.stringify(err)}`,
ToastAndroid.LONG
);
}
};

if (updateCheckRes.isAvailable) {
performUpdateAlert();
} else {
ToastAndroid.show('No updates available', ToastAndroid.SHORT);
}
} catch (err) {
Alert.alert(
'Error checking for updates',
JSON.stringify(err, null, 2)
);
}
};
const performUpdateAlert = useCallback(() => {
Alert.alert(
availableUpdate?.createdAt
? `New update available:\n${availableUpdate?.createdAt.toLocaleString()}`
: 'New update available',
'Do you want to update now?',
[
{ text: 'Cancel' },
{
text: 'OK',
onPress: isUpdatePending
? () => RNRestart.Restart()
: fetchUpdateAndRestart,
},
]
);
}, [availableUpdate?.createdAt, isUpdatePending]);

const handleUpdatePress = isUpdatePending ? performUpdateAlert : checkForUpdate;
const description = isDownloading
? 'Downloading update...'
: isUpdatePending
? 'Update is pending...'
: isChecking
? 'Checking for updates...'
: `Last checked: ${lastCheck?.toLocaleString() || 'Never'}`;
const checkForUpdate = async () => {
try {
const updateCheckRes = await Updates.checkForUpdateAsync();

const renderUpdateIcon = useCallback((props: any) => {
const updateIcon = isUpdatePending
? 'progress-download'
: 'cloud-download-outline';
if (updateCheckRes.isAvailable) {
performUpdateAlert();
} else {
ToastAndroid.show('No updates available', ToastAndroid.SHORT);
}
} catch (err) {
Alert.alert(
'Error checking for updates',
JSON.stringify(err, null, 2)
);
}
};

return (
<List.Icon
{...props}
icon={updateIcon}
color={isUpdatePending
? appTheme.colors.primary
: props.color}
/>
);
}, [appTheme.colors.primary, isUpdatePending]);
const handleUpdatePress = isLatest ?
isUpdatePending ? performUpdateAlert : checkForUpdate
: () => Alert.alert(
'New version available',
`Your version: ${packageData.version}\nLatest version: ${latestRelease}`,
[
{ text: 'Cancel' },
{
text: 'OK', onPress: () => {
Linking.openURL(data?.assets_url || 'https://github.com');
}
}
]
);

const isProcessing = isChecking || isDownloading;
const renderActivityIndicator = useCallback((props: any) => (
isProcessing ? <ActivityIndicator {...props} /> : null
), [isProcessing]);
const description = isDownloading
? 'Downloading update...'
: isUpdatePending
? 'Update is pending...'
: isChecking
? 'Checking for updates...'
: `Last checked: ${lastCheck?.toLocaleString() || 'Never'}`;

const renderUpdateIcon = useCallback((props: any) => {
const updateIcon = isUpdatePending
? 'progress-download'
: 'cloud-download-outline';

return (
<List.Item
title="Check for updates"
description={description}
onPress={handleUpdatePress}
onLongPress={showCurrent}
disabled={isProcessing}
left={renderUpdateIcon}
right={renderActivityIndicator}
/>
<List.Icon
{...props}
icon={updateIcon}
color={isUpdatePending
? appTheme.colors.primary
: props.color}
/>
);
}, [appTheme.colors.primary, isUpdatePending]);

const isProcessing = isChecking || isDownloading;
const renderActivityIndicator = useCallback((props: any) => (
isProcessing ? <ActivityIndicator {...props} /> : null
), [isProcessing]);

return (
<List.Item
title="Check for updates"
description={description}
onPress={handleUpdatePress}
onLongPress={showCurrent}
disabled={isProcessing}
left={renderUpdateIcon}
right={renderActivityIndicator}
/>
);
};
58 changes: 58 additions & 0 deletions src/types/latestRelease.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
export interface Main {
url: string;
assets_url: string;
upload_url: string;
html_url: string;
id: number;
author: Author;
node_id: string;
tag_name: string;
target_commitish: string;
name: string;
draft: boolean;
prerelease: boolean;
created_at: Date;
published_at: Date;
assets: Asset[];
tarball_url: string;
zipball_url: string;
body: string;
}

export interface Asset {
url: string;
id: number;
node_id: string;
name: string;
label: string;
uploader: Author;
content_type: string;
state: string;
size: number;
download_count: number;
created_at: Date;
updated_at: Date;
browser_download_url: string;
}

export interface Author {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
user_view_type: string;
site_admin: boolean;
}

0 comments on commit 13efa81

Please sign in to comment.