Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions ios/RNKitCodePush.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
9F394D881C7C25DC00C794C0 /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F394D761C7C25DC00C794C0 /* unzip.c */; };
9F394D891C7C25DC00C794C0 /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F394D781C7C25DC00C794C0 /* zip.c */; };
9F394D8A1C7C25DC00C794C0 /* SSZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F394D7B1C7C25DC00C794C0 /* SSZipArchive.m */; };
E1162A861FCFE99D005B2A29 /* RNKitMissingImageFixToolBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = E1162A841FCFE99D005B2A29 /* RNKitMissingImageFixToolBridge.m */; };
E1162A871FCFE99D005B2A29 /* RCTConvert+rnkit_missingImage.m in Sources */ = {isa = PBXBuildFile; fileRef = E1162A851FCFE99D005B2A29 /* RCTConvert+rnkit_missingImage.m */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand Down Expand Up @@ -90,6 +92,10 @@
9F394D7A1C7C25DC00C794C0 /* SSZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSZipArchive.h; sourceTree = "<group>"; };
9F394D7B1C7C25DC00C794C0 /* SSZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSZipArchive.m; sourceTree = "<group>"; };
9F394D7C1C7C25DC00C794C0 /* ZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipArchive.h; sourceTree = "<group>"; };
E1162A821FCFE99D005B2A29 /* RCTConvert+rnkit_missingImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+rnkit_missingImage.h"; sourceTree = "<group>"; };
E1162A831FCFE99D005B2A29 /* RNKitMissingImageFixToolBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNKitMissingImageFixToolBridge.h; sourceTree = "<group>"; };
E1162A841FCFE99D005B2A29 /* RNKitMissingImageFixToolBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNKitMissingImageFixToolBridge.m; sourceTree = "<group>"; };
E1162A851FCFE99D005B2A29 /* RCTConvert+rnkit_missingImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+rnkit_missingImage.m"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -122,6 +128,7 @@
91C5F0011C76ECA90037E727 /* RNKitCodePush */ = {
isa = PBXGroup;
children = (
E1162A811FCFE99D005B2A29 /* MissingImageFixTool */,
9F1BCB381CAF6B3E000EF2CB /* BSDiff */,
9F394D571C7C25DC00C794C0 /* SSZipArchive */,
3F50BE3A1E812F8E003A6F64 /* RNKitCodePush.h */,
Expand Down Expand Up @@ -213,6 +220,17 @@
path = minizip;
sourceTree = "<group>";
};
E1162A811FCFE99D005B2A29 /* MissingImageFixTool */ = {
isa = PBXGroup;
children = (
E1162A821FCFE99D005B2A29 /* RCTConvert+rnkit_missingImage.h */,
E1162A851FCFE99D005B2A29 /* RCTConvert+rnkit_missingImage.m */,
E1162A831FCFE99D005B2A29 /* RNKitMissingImageFixToolBridge.h */,
E1162A841FCFE99D005B2A29 /* RNKitMissingImageFixToolBridge.m */,
);
path = MissingImageFixTool;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -273,6 +291,7 @@
9F394D811C7C25DC00C794C0 /* fileenc.c in Sources */,
9F394D871C7C25DC00C794C0 /* mztools.c in Sources */,
9F394D821C7C25DC00C794C0 /* hmac.c in Sources */,
E1162A861FCFE99D005B2A29 /* RNKitMissingImageFixToolBridge.m in Sources */,
9F394D881C7C25DC00C794C0 /* unzip.c in Sources */,
9F1BCB4F1CAF6B68000EF2CB /* BSDiff.m in Sources */,
3F50BE401E812F8E003A6F64 /* RNKitCodePush.m in Sources */,
Expand All @@ -283,6 +302,7 @@
9F394D801C7C25DC00C794C0 /* entropy.c in Sources */,
9F394D831C7C25DC00C794C0 /* prng.c in Sources */,
9F394D861C7C25DC00C794C0 /* ioapi.c in Sources */,
E1162A871FCFE99D005B2A29 /* RCTConvert+rnkit_missingImage.m in Sources */,
9F1BCB461CAF6B3E000EF2CB /* bspatch.c in Sources */,
9F394D8A1C7C25DC00C794C0 /* SSZipArchive.m in Sources */,
9F394D891C7C25DC00C794C0 /* zip.c in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// RCTConvert+rnkit_missingImage.h
// RNKitCodePush
//
// Created by aevit on 2017/11/30.
// Copyright © 2017年 erica. All rights reserved.
//

#import <Foundation/Foundation.h>

/**
sometimes when patch completed, some images are missing, until 2017.11.30, still don't know why.
so, use swizzle to solve this problem in the other way: if the image doesn't exist in the sanbox, search the bundle.

@param _assetsPath the ReactNative Framework will put the images to directory "assets" in the main bundle by default, but when you change to the different directory, remember that the parameter "assetPath" should change too.
@return
*/
void installMissingImageFixTool(NSString *_assetsPath);

/**
swizzle origin methods
*/
void uninstallMissingImageFixTool();

Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// RCTConvert+rnkit_missingImage.m
// RNKitCodePush
//
// Created by aevit on 2017/11/30.
// Copyright © 2017年 erica. All rights reserved.
//

#import "RCTConvert+rnkit_missingImage.h"
#import <React/RCTImageSource.h>
#import <objc/runtime.h>
#import "RNKitCodePush.h"

@implementation RCTConvert (rnkit_missingImage)
static BOOL sc_installed = NO;
static NSString *sc_assetsPath = nil;

#pragma mark ---------- public methods
void installMissingImageFixTool(NSString *_assetsPath) {
dispatch_semaphore_t lock = dispatch_semaphore_create(1);
dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
if (!sc_installed) {
sc_installed = YES;
sc_assetsPath = _assetsPath ?: @"assets/";
swizzleRCTImageSourceMethod();
}
dispatch_semaphore_signal(lock);
}

void uninstallMissingImageFixTool() {
dispatch_semaphore_t lock = dispatch_semaphore_create(1);
dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
if (sc_installed) {
sc_installed = NO;
sc_assetsPath = nil;
swizzleRCTImageSourceMethod();
}
dispatch_semaphore_signal(lock);
}

#pragma mark - private methods
void swizzleRCTImageSourceMethod() {

Class class = object_getClass((id)[RCTConvert class]);

SEL originalSel = sel_registerName("RCTImageSource:");
SEL swizzleSel = sel_registerName("swizzleRCTImageSource:");

Method originalMethod = class_getClassMethod(class, originalSel);
Method swizzleMethod = class_getClassMethod(class, swizzleSel);

BOOL success = class_addMethod(class, originalSel, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
if (success) {
class_replaceMethod(class, swizzleSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
} else {
method_exchangeImplementations(originalMethod, swizzleMethod);
}
}

+ (RCTImageSource *)swizzleRCTImageSource:(id)json {
if ([RNKitCodePush hasUpdateInfo] && json && [json isKindOfClass:[NSDictionary class]] && json[@"uri"] && [json[@"uri"] hasPrefix:@"file://"]) {
NSString *path = json[@"uri"];
if (![[self class] isExistInRNKitCodePush:path]) {
path = [[self class] convertToBundlePath:path];
if (path) {
NSMutableDictionary *aDict = [NSMutableDictionary dictionaryWithDictionary:json];
aDict[@"uri"] = [NSString stringWithFormat:@"file://%@", path];
return [RCTConvert swizzleRCTImageSource:aDict];
}
}
}
return [RCTConvert swizzleRCTImageSource:json];
}

+ (BOOL)isExistInRNKitCodePush:(NSString*)uri {
NSString *path = [uri stringByReplacingOccurrencesOfString:@"file://" withString:@""];
NSRange range = [path rangeOfString:@"rnkitcodepush/"];
if (range.location != NSNotFound) {
path = [NSString stringWithFormat:@"%@/%@", [RNKitCodePush downloadDir], [path substringFromIndex:(range.location + range.length)]];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
return YES;
}
}
return NO;
}

+ (NSString*)convertToBundlePath:(NSString*)uri {
NSString *path = [uri stringByReplacingOccurrencesOfString:@"file://" withString:@""];
NSRange range = [path rangeOfString:sc_assetsPath];
if (range.location != NSNotFound) {
path = [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] bundlePath], [path substringFromIndex:range.location]];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
return path;
}
}
return nil;
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// RNKitMissingImageFixToolBridge.h
// RNKitCodePush
//
// Created by aevit on 2017/11/30.
// Copyright © 2017年 erica. All rights reserved.
//

#import <Foundation/Foundation.h>
#if __has_include(<React/RCTBridge.h>)
#import <React/RCTBridgeModule.h>
#else
#import "RCTBridgeModule.h"
#endif

@interface RNKitMissingImageFixToolBridge : NSObject <RCTBridgeModule>

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// RNKitMissingImageFixToolBridge.m
// RNKitCodePush
//
// Created by aevit on 2017/11/30.
// Copyright © 2017年 erica. All rights reserved.
//

#import "RNKitMissingImageFixToolBridge.h"
#import "RCTConvert+rnkit_missingImage.h"

@implementation RNKitMissingImageFixToolBridge

RCT_EXPORT_MODULE(RNKitMissingImageFixToolBridge);

RCT_EXPORT_METHOD(installMissingImageFixTool:(NSString*)assetsPath) {
installMissingImageFixTool(assetsPath);
}

RCT_EXPORT_METHOD(uninstallMissingImageFixTool) {
uninstallMissingImageFixTool();
}

@end
4 changes: 4 additions & 0 deletions ios/RNKitCodePush/RNKitCodePush.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@

+ (NSURL *)bundleURL;

+ (BOOL)hasUpdateInfo;

+ (NSString *)downloadDir;

@end
4 changes: 4 additions & 0 deletions ios/RNKitCodePush/RNKitCodePush.m
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ + (NSURL *)bundleURL
return [RNKitCodePush binaryBundleURL];
}

+ (BOOL)hasUpdateInfo {
return [[NSUserDefaults standardUserDefaults] dictionaryForKey:keyUpdateInfo] ? YES : NO;
}

- (NSDictionary *)constantsToExport
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
Expand Down
27 changes: 27 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
* @author SimMan <liwei0990@gmail.com>
* @copyright 2011-2017 RNKit.io, Inc.
*/
import {
NativeModules,
Platform
} from 'react-native'

const RNKitCodePushModule = require('react-native').NativeModules.RNKitCodePush

let apiHost = 'https://update.rnkit.io/api/v1'
Expand Down Expand Up @@ -45,6 +50,28 @@ export default class RNKitCodePush {
return RNKitCodePushModule.deviceInfo
}

/**
* sometimes when patch completed, some images are missing, until 2017.11.30, still don't know why.
* so in iOS, use swizzle to solve this problem in the other way: if the image doesn't exist in the sanbox, search the bundle.
*
* @param {any} assetPath the ReactNative Framework will put the images to directory "assets" in the main bundle by default,
* but when you change to the different directory, remember that the parameter "assetPath" should change too.
* @memberof RNKitCodePush
*/
installMissingImageFixTool(assetPath) {
const { RNKitMissingImageFixToolBridge } = NativeModules
if (Platform.OS === 'ios' && RNKitMissingImageFixToolBridge && RNKitMissingImageFixToolBridge.installMissingImageFixTool) {
RNKitMissingImageFixToolBridge.installMissingImageFixTool(assetPath ? assetPath : 'assets/')
}
}

uninstallMissingImageFixTool() {
const { RNKitMissingImageFixToolBridge } = NativeModules
if (Platform.OS === 'ios' && RNKitMissingImageFixToolBridge && RNKitMissingImageFixToolBridge.uninstallMissingImageFixTool) {
RNKitMissingImageFixToolBridge.uninstallMissingImageFixTool()
}
}

// check update from service
async checkUpdate () {
const resp = await fetch(`${this.host}/update/check`, {
Expand Down