mirror of
				https://gitcode.com/gh_mirrors/re/react-native-pushy.git
				synced 2025-10-31 21:33:12 +08:00 
			
		
		
		
	Implement download progress
This commit is contained in:
		| @@ -27,6 +27,10 @@ import _updateConfig from '../update.json'; | |||||||
| const {appKey} = _updateConfig[Platform.OS]; | const {appKey} = _updateConfig[Platform.OS]; | ||||||
|  |  | ||||||
| export default class App extends Component { | export default class App extends Component { | ||||||
|  |   state = { | ||||||
|  |     received: 0, | ||||||
|  |     total: 0, | ||||||
|  |   }; | ||||||
|   componentDidMount() { |   componentDidMount() { | ||||||
|     if (isRolledBack) { |     if (isRolledBack) { | ||||||
|       Alert.alert('提示', '刚刚更新失败了,版本被回滚.'); |       Alert.alert('提示', '刚刚更新失败了,版本被回滚.'); | ||||||
| @@ -51,9 +55,16 @@ export default class App extends Component { | |||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   doUpdate = async info => { |   doUpdate = async (info) => { | ||||||
|     try { |     try { | ||||||
|       const hash = await downloadUpdate(info); |       const hash = await downloadUpdate(info, { | ||||||
|  |         onDownloadProgress: ({received, total}) => { | ||||||
|  |           setState({ | ||||||
|  |             received, | ||||||
|  |             total, | ||||||
|  |           }); | ||||||
|  |         }, | ||||||
|  |       }); | ||||||
|       Alert.alert('提示', '下载完毕,是否重启应用?', [ |       Alert.alert('提示', '下载完毕,是否重启应用?', [ | ||||||
|         { |         { | ||||||
|           text: '是', |           text: '是', | ||||||
| @@ -126,6 +137,9 @@ export default class App extends Component { | |||||||
|           当前热更新版本Hash: {currentVersion || '(空)'} |           当前热更新版本Hash: {currentVersion || '(空)'} | ||||||
|           {'\n'} |           {'\n'} | ||||||
|         </Text> |         </Text> | ||||||
|  |         <Text> | ||||||
|  |           下载进度:{received} / {total} | ||||||
|  |         </Text> | ||||||
|         <TouchableOpacity onPress={this.checkUpdate}> |         <TouchableOpacity onPress={this.checkUpdate}> | ||||||
|           <Text style={styles.instructions}>点击这里检查更新</Text> |           <Text style={styles.instructions}>点击这里检查更新</Text> | ||||||
|         </TouchableOpacity> |         </TouchableOpacity> | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -6,13 +6,11 @@ | |||||||
| //  Copyright © 2016 erica. All rights reserved. | //  Copyright © 2016 erica. All rights reserved. | ||||||
| // | // | ||||||
|  |  | ||||||
| #if __has_include(<React/RCTBridge.h>) |  | ||||||
| #import <React/RCTBridgeModule.h> | #import <React/RCTBridgeModule.h> | ||||||
| #else | #import <React/RCTEventEmitter.h> | ||||||
| #import "RCTBridgeModule.h" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| @interface RCTPushy : NSObject<RCTBridgeModule> |  | ||||||
|  | @interface RCTPushy : RCTEventEmitter<RCTBridgeModule> | ||||||
|  |  | ||||||
| + (NSURL *)bundleURL; | + (NSURL *)bundleURL; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,17 +10,11 @@ | |||||||
| #import "RCTPushyDownloader.h" | #import "RCTPushyDownloader.h" | ||||||
| #import "RCTPushyManager.h" | #import "RCTPushyManager.h" | ||||||
|  |  | ||||||
| #if __has_include(<React/RCTBridge.h>) |  | ||||||
| #import "React/RCTEventDispatcher.h" |  | ||||||
| #import <React/RCTConvert.h> | #import <React/RCTConvert.h> | ||||||
| #import <React/RCTLog.h> | #import <React/RCTLog.h> | ||||||
| #else | #import <React/RCTReloadCommand.h> | ||||||
| #import "RCTEventDispatcher.h" |  | ||||||
| #import "RCTConvert.h" |  | ||||||
| #import "RCTLog.h" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| // |  | ||||||
| static NSString *const keyPushyInfo = @"REACTNATIVECN_PUSHY_INFO_KEY"; | static NSString *const keyPushyInfo = @"REACTNATIVECN_PUSHY_INFO_KEY"; | ||||||
| static NSString *const paramPackageVersion = @"packageVersion"; | static NSString *const paramPackageVersion = @"packageVersion"; | ||||||
| static NSString *const paramLastVersion = @"lastVersion"; | static NSString *const paramLastVersion = @"lastVersion"; | ||||||
| @@ -65,6 +59,7 @@ static BOOL ignoreRollback = false; | |||||||
|  |  | ||||||
| @implementation RCTPushy { | @implementation RCTPushy { | ||||||
|     RCTPushyManager *_fileManager; |     RCTPushyManager *_fileManager; | ||||||
|  |     bool hasListeners; | ||||||
| } | } | ||||||
|  |  | ||||||
| @synthesize bridge = _bridge; | @synthesize bridge = _bridge; | ||||||
| @@ -281,10 +276,12 @@ RCT_EXPORT_METHOD(reloadUpdate:(NSDictionary *)options) | |||||||
|         [self setNeedUpdate:options]; |         [self setNeedUpdate:options]; | ||||||
|          |          | ||||||
|         // reload |         // reload | ||||||
|         dispatch_async(dispatch_get_main_queue(), ^{ |         RCTReloadCommandSetBundleURL([[self class] bundleURL]); | ||||||
|             [_bridge setValue:[[self class] bundleURL] forKey:@"bundleURL"]; |         RCTTriggerReloadCommandListeners(@"pushy reload"); | ||||||
|             [_bridge reload]; | //        dispatch_async(dispatch_get_main_queue(), ^{ | ||||||
|         }); | //            [self.bridge setValue:[[self class] bundleURL] forKey:@"bundleURL"]; | ||||||
|  | //            [self.bridge reload]; | ||||||
|  | //        }); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -302,7 +299,27 @@ RCT_EXPORT_METHOD(markSuccess) | |||||||
|     [self clearInvalidFiles]; |     [self clearInvalidFiles]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #pragma mark - private | #pragma mark - private | ||||||
|  | - (NSArray<NSString *> *)supportedEvents | ||||||
|  | { | ||||||
|  |   return @[EVENT_PROGRESS_DOWNLOAD, EVENT_PROGRESS_UNZIP]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Will be called when this module's first listener is added. | ||||||
|  | -(void)startObserving { | ||||||
|  |     hasListeners = YES; | ||||||
|  |     // Set up any upstream listeners or background tasks as necessary | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Will be called when this module's last listener is removed, or on dealloc. | ||||||
|  | -(void)stopObserving { | ||||||
|  |     hasListeners = NO; | ||||||
|  |     // Remove upstream listeners, stop unnecessary background tasks | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| - (void)doPushy:(PushyType)type options:(NSDictionary *)options callback:(void (^)(NSError *error))callback | - (void)doPushy:(PushyType)type options:(NSDictionary *)options callback:(void (^)(NSError *error))callback | ||||||
| { | { | ||||||
|     NSString *updateUrl = [RCTConvert NSString:options[@"updateUrl"]]; |     NSString *updateUrl = [RCTConvert NSString:options[@"updateUrl"]]; | ||||||
| @@ -325,16 +342,17 @@ RCT_EXPORT_METHOD(markSuccess) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     NSString *zipFilePath = [dir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",hashName, [self zipExtension:type]]]; |     NSString *zipFilePath = [dir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",hashName, [self zipExtension:type]]]; | ||||||
|     NSString *unzipDir = [dir stringByAppendingPathComponent:hashName]; | //    NSString *unzipDir = [dir stringByAppendingPathComponent:hashName]; | ||||||
|  |  | ||||||
|     RCTLogInfo(@"RCTPushy -- download file %@", updateUrl); |     RCTLogInfo(@"RCTPushy -- download file %@", updateUrl); | ||||||
|     [RCTPushyDownloader download:updateUrl savePath:zipFilePath progressHandler:^(long long receivedBytes, long long totalBytes) { |     [RCTPushyDownloader download:updateUrl savePath:zipFilePath progressHandler:^(long long receivedBytes, long long totalBytes) { | ||||||
|         [self.bridge.eventDispatcher sendAppEventWithName:EVENT_PROGRESS_DOWNLOAD |         if (self->hasListeners) { | ||||||
|                                                      body:@{ |             [self sendEventWithName:EVENT_PROGRESS_DOWNLOAD body:@{ | ||||||
|                                                             PARAM_PROGRESS_HASHNAME:hashName, |                 PARAM_PROGRESS_HASHNAME:hashName, | ||||||
|                                                             PARAM_PROGRESS_RECEIVED:[NSNumber numberWithLongLong:receivedBytes], |                 PARAM_PROGRESS_RECEIVED:[NSNumber numberWithLongLong:receivedBytes], | ||||||
|                                                             PARAM_PROGRESS_TOTAL:[NSNumber numberWithLongLong:totalBytes] |                 PARAM_PROGRESS_TOTAL:[NSNumber numberWithLongLong:totalBytes] | ||||||
|                                                             }]; |             }]; | ||||||
|  |         } | ||||||
|     } completionHandler:^(NSString *path, NSError *error) { |     } completionHandler:^(NSString *path, NSError *error) { | ||||||
|         if (error) { |         if (error) { | ||||||
|             callback(error); |             callback(error); | ||||||
| @@ -342,16 +360,18 @@ RCT_EXPORT_METHOD(markSuccess) | |||||||
|         else { |         else { | ||||||
|             RCTLogInfo(@"RCTPushy -- unzip file %@", zipFilePath); |             RCTLogInfo(@"RCTPushy -- unzip file %@", zipFilePath); | ||||||
|             NSString *unzipFilePath = [dir stringByAppendingPathComponent:hashName]; |             NSString *unzipFilePath = [dir stringByAppendingPathComponent:hashName]; | ||||||
|             [_fileManager unzipFileAtPath:zipFilePath toDestination:unzipFilePath progressHandler:^(NSString *entry,long entryNumber, long total) { |             [self->_fileManager unzipFileAtPath:zipFilePath toDestination:unzipFilePath progressHandler:^(NSString *entry,long entryNumber, long total) { | ||||||
|                 [self.bridge.eventDispatcher sendAppEventWithName:EVENT_PROGRESS_UNZIP |                 if (self->hasListeners) { | ||||||
|                                                              body:@{ |                     [self sendEventWithName:EVENT_PROGRESS_UNZIP | ||||||
|                                                                     PARAM_PROGRESS_HASHNAME:hashName, |                                        body:@{ | ||||||
|                                                                     PARAM_PROGRESS_RECEIVED:[NSNumber numberWithLong:entryNumber], |                                            PARAM_PROGRESS_HASHNAME:hashName, | ||||||
|                                                                     PARAM_PROGRESS_TOTAL:[NSNumber numberWithLong:total] |                                            PARAM_PROGRESS_RECEIVED:[NSNumber numberWithLong:entryNumber], | ||||||
|                                                                     }]; |                                            PARAM_PROGRESS_TOTAL:[NSNumber numberWithLong:total] | ||||||
|  |                                        }]; | ||||||
|  |                 } | ||||||
|                  |                  | ||||||
|             } completionHandler:^(NSString *path, BOOL succeeded, NSError *error) { |             } completionHandler:^(NSString *path, BOOL succeeded, NSError *error) { | ||||||
|                 dispatch_async(_methodQueue, ^{ |                 dispatch_async(self->_methodQueue, ^{ | ||||||
|                     if (error) { |                     if (error) { | ||||||
|                         callback(error); |                         callback(error); | ||||||
|                     } |                     } | ||||||
| @@ -404,7 +424,7 @@ RCT_EXPORT_METHOD(markSuccess) | |||||||
|             NSDictionary *copies = json[@"copies"]; |             NSDictionary *copies = json[@"copies"]; | ||||||
|             NSDictionary *deletes = json[@"deletes"]; |             NSDictionary *deletes = json[@"deletes"]; | ||||||
|  |  | ||||||
|             [_fileManager copyFiles:copies fromDir:sourceOrigin toDir:unzipDir deletes:deletes completionHandler:^(NSError *error) { |             [self->_fileManager copyFiles:copies fromDir:sourceOrigin toDir:unzipDir deletes:deletes completionHandler:^(NSError *error) { | ||||||
|                 if (error) { |                 if (error) { | ||||||
|                     callback(error); |                     callback(error); | ||||||
|                 } |                 } | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								lib/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								lib/index.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -31,7 +31,11 @@ export type CheckResult = | |||||||
| export function checkUpdate(appkey: string): Promise<CheckResult>; | export function checkUpdate(appkey: string): Promise<CheckResult>; | ||||||
|  |  | ||||||
| export function downloadUpdate( | export function downloadUpdate( | ||||||
|   options: UpdateAvailableResult, |   info: UpdateAvailableResult, | ||||||
|  |   eventListeners?: { | ||||||
|  |     onDownloadProgress?: (data: ProgressData) => void; | ||||||
|  |     onUnzipProgress?: (data: ProgressData) => void; | ||||||
|  |   }, | ||||||
| ): Promise<undefined | string>; | ): Promise<undefined | string>; | ||||||
|  |  | ||||||
| export function switchVersion(hash: string): void; | export function switchVersion(hash: string): void; | ||||||
| @@ -56,8 +60,8 @@ export function setCustomEndpoints({ | |||||||
|   backupQueryUrl?: string; |   backupQueryUrl?: string; | ||||||
| }): void; | }): void; | ||||||
|  |  | ||||||
|  | interface ProgressData { | ||||||
| interface ProgressEvent { |   hashname: string; | ||||||
|   received: number; |   received: number; | ||||||
|   total: number; |   total: number; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								lib/index.js
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								lib/index.js
									
									
									
									
									
								
							| @@ -3,7 +3,7 @@ import { | |||||||
|   getCheckUrl, |   getCheckUrl, | ||||||
|   setCustomEndpoints, |   setCustomEndpoints, | ||||||
| } from './endpoint'; | } from './endpoint'; | ||||||
| import { NativeAppEventEmitter, NativeModules, Platform } from 'react-native'; | import { NativeEventEmitter, NativeModules, Platform } from 'react-native'; | ||||||
| export { setCustomEndpoints }; | export { setCustomEndpoints }; | ||||||
| const { | const { | ||||||
|   version: v, |   version: v, | ||||||
| @@ -32,12 +32,18 @@ if (Platform.OS === 'android' && !Pushy.isUsingBundleUrl) { | |||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | const eventEmitter = new NativeEventEmitter(Pushy); | ||||||
|  |  | ||||||
| if (!uuid) { | if (!uuid) { | ||||||
|   uuid = uuidv4(); |   uuid = uuidv4(); | ||||||
|   Pushy.setUuid(uuid); |   Pushy.setUuid(uuid); | ||||||
| } | } | ||||||
|  |  | ||||||
| console.log('Pushy uuid: ' + uuid); | function logger(text) { | ||||||
|  |   console.log(`Pushy: ${text}`); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | logger('uuid: ' + uuid); | ||||||
|  |  | ||||||
| /* | /* | ||||||
| Return json: | Return json: | ||||||
| @@ -77,6 +83,10 @@ export async function checkUpdate(APPKEY, isRetry) { | |||||||
|       ).toLocaleString()}"之后重试。`, |       ).toLocaleString()}"之后重试。`, | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |   if (typeof APPKEY !== 'string') { | ||||||
|  |     throw new Error('未检查到合法的APPKEY,请查看update.json文件是否正确生成'); | ||||||
|  |   } | ||||||
|  |   logger('checking update'); | ||||||
|   let resp; |   let resp; | ||||||
|   try { |   try { | ||||||
|     resp = await fetch(getCheckUrl(APPKEY), { |     resp = await fetch(getCheckUrl(APPKEY), { | ||||||
| @@ -129,41 +139,62 @@ function checkOperation(op) { | |||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| export async function downloadUpdate(options) { | export async function downloadUpdate(options, eventListeners) { | ||||||
|   assertRelease(); |   assertRelease(); | ||||||
|   if (!options.update) { |   if (!options.update) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |   if (eventListeners) { | ||||||
|  |     if (eventListeners.onDownloadProgress) { | ||||||
|  |       const downloadCallback = eventListeners.onDownloadProgress; | ||||||
|  |       eventEmitter.addListener('RCTPushyDownloadProgress', (progressData) => { | ||||||
|  |         if (progressData.hash === options.hash) { | ||||||
|  |           downloadCallback(progressData); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if (eventListeners.onUnzipProgress) { | ||||||
|  |       const unzipCallback = eventListeners.onUnzipProgress; | ||||||
|  |       eventEmitter.addListener('RCTPushyUnzipProgress', (progressData) => { | ||||||
|  |         if (progressData.hash === options.hash) { | ||||||
|  |           unzipCallback(progressData); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|   if (options.diffUrl) { |   if (options.diffUrl) { | ||||||
|  |     logger('downloading diff'); | ||||||
|     await Pushy.downloadPatchFromPpk({ |     await Pushy.downloadPatchFromPpk({ | ||||||
|       updateUrl: options.diffUrl, |       updateUrl: options.diffUrl, | ||||||
|       hashName: options.hash, |       hashName: options.hash, | ||||||
|       originHashName: currentVersion, |       originHashName: currentVersion, | ||||||
|     }); |     }); | ||||||
|   } else if (options.pdiffUrl) { |   } else if (options.pdiffUrl) { | ||||||
|  |     logger('downloading pdiff'); | ||||||
|     await Pushy.downloadPatchFromPackage({ |     await Pushy.downloadPatchFromPackage({ | ||||||
|       updateUrl: options.pdiffUrl, |       updateUrl: options.pdiffUrl, | ||||||
|       hashName: options.hash, |       hashName: options.hash, | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |   eventEmitter.removeAllListeners('RCTPushyDownloadProgress'); | ||||||
|  |   eventEmitter.removeAllListeners('RCTPushyUnzipProgress'); | ||||||
|   return options.hash; |   return options.hash; | ||||||
| } | } | ||||||
|  |  | ||||||
| export function switchVersion(hash) { | export function switchVersion(hash) { | ||||||
|   assertRelease(); |   assertRelease(); | ||||||
|  |   logger('switchVersion'); | ||||||
|   Pushy.reloadUpdate({ hashName: hash }); |   Pushy.reloadUpdate({ hashName: hash }); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function switchVersionLater(hash) { | export function switchVersionLater(hash) { | ||||||
|   assertRelease(); |   assertRelease(); | ||||||
|  |   logger('switchVersionLater'); | ||||||
|   Pushy.setNeedUpdate({ hashName: hash }); |   Pushy.setNeedUpdate({ hashName: hash }); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function markSuccess() { | export function markSuccess() { | ||||||
|   assertRelease(); |   assertRelease(); | ||||||
|  |   logger('markSuccess'); | ||||||
|   Pushy.markSuccess(); |   Pushy.markSuccess(); | ||||||
| } | } | ||||||
|  |  | ||||||
| NativeAppEventEmitter.addListener('RCTPushyDownloadProgress', (params) => {}); |  | ||||||
|  |  | ||||||
| NativeAppEventEmitter.addListener('RCTPushyUnzipProgress', (params) => {}); |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 sunnylqm
					sunnylqm