mirror of
https://github.com/scratchfoundation/scratchjr.git
synced 2024-11-28 18:15:37 -05:00
iOS: clean up import project and make thumbnails for sprites and backgrounds
This commit is contained in:
parent
397ce34148
commit
468bc4e0ab
7 changed files with 176 additions and 152 deletions
|
@ -65,7 +65,8 @@
|
|||
|
||||
- (BOOL) application:(UIApplication *)application openURL:(NSURL *) url sourceApplication:(NSString *) sourceApplication annotation:(id) annotation {
|
||||
if (url) {
|
||||
[IO receiveProject:url];
|
||||
NSLog(@"openg url: %@", url.absoluteURL);
|
||||
[ScratchJr receiveProject:url];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
|
|
@ -58,14 +58,20 @@ NSString* dberror() {return [NSString stringWithFormat:@"SQL error: %s", sqlite3
|
|||
NSData* data = [body dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:data options: 0 error: nil];
|
||||
// NSLog(@"stmt %@", dict);
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
NSString *stmtstr = [dict objectForKey: @"stmt"];
|
||||
NSArray *values = [dict objectForKey: @"values"];
|
||||
// NSLog(@"stmt %@", stmtstr);
|
||||
return [Database stmt:stmtstr with:values];
|
||||
}
|
||||
|
||||
+ (NSString*) stmt: (NSString *)stmtstr with:(NSArray *) values {
|
||||
sqlite3_stmt *stmt;
|
||||
// NSLog(@"stmt %@", stmtstr);
|
||||
if (!(sqlite3_prepare_v2(db, [stmtstr UTF8String], -1, &stmt, NULL) == SQLITE_OK)) return dberror();
|
||||
for(int i=0;i<[values count];i++)
|
||||
for(int i=0;i<[values count];i++) {
|
||||
sqlite3_bind_text(stmt, i+1, [[values objectAtIndex: i] UTF8String], -1, SQLITE_TRANSIENT);
|
||||
// NSLog(@"stmt done %@", stmtstr);
|
||||
}
|
||||
// NSLog(@"stmt done %@", stmtstr);
|
||||
if (!(sqlite3_step(stmt) == SQLITE_DONE)) return dberror();
|
||||
sqlite3_finalize(stmt);
|
||||
return [NSString stringWithFormat:@"%lld",sqlite3_last_insert_rowid(db)];
|
||||
|
@ -130,22 +136,9 @@ NSString* dberror() {return [NSString stringWithFormat:@"SQL error: %s", sqlite3
|
|||
for (int i = 0; i < data.count; i++) {
|
||||
[placeholders addObject:@"?"];
|
||||
}
|
||||
sqlite3_stmt *stmt;
|
||||
NSString *stmtstr = [NSString stringWithFormat:@"INSERT INTO %@ (%@) VALUES (%@)", table, keys, [placeholders componentsJoinedByString:@","]];
|
||||
NSArray *values = [data allValues];
|
||||
// NSLog(@"stmt %@", stmtstr);
|
||||
if (sqlite3_prepare_v2(db, [stmtstr UTF8String], -1, &stmt, NULL) != SQLITE_OK) {
|
||||
return dberror();
|
||||
}
|
||||
for(int i=0;i<[values count];i++) {
|
||||
sqlite3_bind_text(stmt, i+1, [[values objectAtIndex: i] UTF8String], -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
// NSLog(@"stmt done %@", stmtstr);
|
||||
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
||||
return dberror();
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
return [NSString stringWithFormat:@"%lld", sqlite3_last_insert_rowid(db)];
|
||||
return [Database stmt:stmtstr with:values];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -282,118 +282,126 @@ NSMutableDictionary *soundtimers;
|
|||
}
|
||||
|
||||
+ (void) receiveProject: (NSURL *) url {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSString *tempDir = [[IO getTmpPath:[[NSUUID alloc] init].UUIDString].path stringByAppendingString:@"/"];
|
||||
// uncompress
|
||||
[SSZipArchive unzipFileAtPath:url.path toDestination:tempDir];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
// remove zip
|
||||
// [fileManager removeItemAtURL:url error:nil];
|
||||
NSString *projectPath = [tempDir stringByAppendingString:@"/project/data.json"];
|
||||
|
||||
if (![fileManager fileExistsAtPath:projectPath]) {
|
||||
// project data file doesn't exist
|
||||
return;
|
||||
NSString *tempDir = [[IO getTmpPath:[[NSUUID alloc] init].UUIDString].path stringByAppendingString:@"/"];
|
||||
// uncompress
|
||||
[SSZipArchive unzipFileAtPath:url.path toDestination:tempDir];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
// remove zip
|
||||
[fileManager removeItemAtURL:url error:nil];
|
||||
NSString *projectPath = [tempDir stringByAppendingString:@"/project/data.json"];
|
||||
|
||||
if (![fileManager fileExistsAtPath:projectPath]) {
|
||||
// project data file doesn't exist
|
||||
return;
|
||||
}
|
||||
NSData *data = [[NSData alloc] initWithContentsOfFile:projectPath];
|
||||
NSError *error = nil;
|
||||
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingFragmentsAllowed error:&error];
|
||||
if (error != nil) {
|
||||
// invalid json
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary *project = [[NSMutableDictionary alloc] init];
|
||||
[project setValue:@"1" forKey:@"isgift"];
|
||||
[project setValue:@"NO" forKey:@"deleted"];
|
||||
NSDictionary *json = [dictionary valueForKey:@"json"];
|
||||
[project setValue:[json jsonString] forKey:@"json"];
|
||||
NSDictionary *thumbnail = [dictionary valueForKey:@"thumbnail"];
|
||||
[project setValue:[thumbnail jsonString] forKey:@"thumbnail"];
|
||||
[project setValue:@"iOSv01" forKey:@"version"];
|
||||
[project setValue:[dictionary valueForKey:@"name"] forKey:@"name"];
|
||||
// save project to database
|
||||
[Database insert:@"projects" with:project];
|
||||
NSMutableDictionary *sprites = [[NSMutableDictionary alloc] init];
|
||||
for (NSString *name in [json valueForKey:@"pages"]) {
|
||||
NSDictionary *page = [json valueForKey:name];
|
||||
for (NSString *spriteName in [page valueForKey:@"sprites"]) {
|
||||
NSDictionary *sprite = [page valueForKey:spriteName];
|
||||
[sprites setValue:sprite forKey:[sprite valueForKey:@"md5"]];
|
||||
}
|
||||
NSData *data = [[NSData alloc] initWithContentsOfFile:projectPath];
|
||||
NSError *error = nil;
|
||||
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingFragmentsAllowed error:&error];
|
||||
if (error != nil) {
|
||||
// invalid json
|
||||
return;
|
||||
}
|
||||
|
||||
// read project data
|
||||
// create project
|
||||
NSDirectoryEnumerator<NSString *> * enumerator = [fileManager enumeratorAtPath:tempDir];
|
||||
NSString *path;
|
||||
while ((path = [enumerator nextObject]) != nil) {
|
||||
// only copy image and sounds
|
||||
if (![path hasSuffix:@".png"] && ![path hasSuffix:@".wav"] && ![path hasSuffix:@".svg"]) {
|
||||
continue;
|
||||
}
|
||||
NSString *fileName = [path lastPathComponent];
|
||||
NSArray *parts = [path componentsSeparatedByString:@"/"];
|
||||
if (parts.count < 2) {
|
||||
continue;
|
||||
}
|
||||
NSString *folder = parts[1];
|
||||
// extract files
|
||||
NSString *toPath = [[IO getpath] stringByAppendingPathComponent:fileName];
|
||||
if (![fileManager fileExistsAtPath: toPath]) {
|
||||
// NSLog(@"copy file to path %@", toPath);
|
||||
NSString *fromPath = [tempDir stringByAppendingString:path];
|
||||
[fileManager copyItemAtPath:fromPath toPath:toPath error:&error];
|
||||
if (error != nil) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ([folder isEqualToString:@"sounds"] || [folder isEqualToString:@"thumbnails"]) {
|
||||
// process for sounds and thumbnails is done
|
||||
continue;
|
||||
}
|
||||
// save background or shape to database.
|
||||
NSString *table = [folder isEqualToString:@"characters"] ? @"usershapes" : @"userbkgs";
|
||||
NSMutableArray *values = [[NSMutableArray alloc] init];
|
||||
[values addObject:fileName];
|
||||
// check database
|
||||
NSString *stmt = [NSString stringWithFormat:@"SELECT id FROM %@ WHERE md5 = ?", table];
|
||||
NSArray *res = [Database findDataIn:stmt with:values];
|
||||
// TODO: if query encounter an error, res.count will also be greater than 0
|
||||
if (res.count > 0) {
|
||||
continue;
|
||||
}
|
||||
// insert into database
|
||||
NSLog(@"%@ not exists, creating", fileName);
|
||||
NSMutableDictionary *asset = [[NSMutableDictionary alloc] init];
|
||||
|
||||
NSString *pngName = [fileName stringByReplacingOccurrencesOfString:@".svg" withString:@".png"];
|
||||
|
||||
[asset setValue:@"iOSv01" forKey:@"version"];
|
||||
[asset setValue:pngName forKey:@"altmd5"];
|
||||
[asset setValue:fileName forKey:@"md5"];
|
||||
[asset setValue:[fileName pathExtension] forKey:@"ext"];
|
||||
[asset setValue:@"480" forKey:@"width"];
|
||||
[asset setValue:@"360" forKey:@"height"];
|
||||
|
||||
if ([folder isEqualToString:@"characters"]) {
|
||||
// create shape
|
||||
NSDictionary *sprite = [sprites valueForKey:fileName];
|
||||
if (sprite == nil) {
|
||||
continue;
|
||||
}
|
||||
// we need all values to be NSString
|
||||
NSString *width = [sprite valueForKey:@"w"];
|
||||
NSString *height = [sprite valueForKey:@"h"];
|
||||
NSString *scale = [sprite valueForKey:@"scale"];
|
||||
[asset setValue:[NSString stringWithFormat:@"%@", width] forKey:@"width"];
|
||||
[asset setValue:[NSString stringWithFormat:@"%@", height] forKey:@"height"];
|
||||
[asset setValue:[NSString stringWithFormat:@"%@", scale] forKey:@"scale"];
|
||||
[asset setValue:[sprite valueForKey:@"id"] forKey:@"name"];
|
||||
}
|
||||
|
||||
NSMutableDictionary *project = [[NSMutableDictionary alloc] init];
|
||||
[project setValue:@"1" forKey:@"isgift"];
|
||||
[project setValue:@"NO" forKey:@"deleted"];
|
||||
NSDictionary *json = [dictionary valueForKey:@"json"];
|
||||
[project setValue:[json jsonString] forKey:@"json"];
|
||||
NSDictionary *thumbnail = [dictionary valueForKey:@"thumbnail"];
|
||||
[project setValue:[thumbnail jsonString] forKey:@"thumbnail"];
|
||||
[project setValue:@"iOSv01" forKey:@"version"];
|
||||
[project setValue:[dictionary valueForKey:@"name"] forKey:@"name"];
|
||||
// save project to database
|
||||
[Database insert:@"projects" with:project];
|
||||
NSMutableDictionary *sprites = [[NSMutableDictionary alloc] init];
|
||||
for (NSString *name in [json valueForKey:@"pages"]) {
|
||||
NSDictionary *page = [json valueForKey:name];
|
||||
for (NSString *spriteName in [page valueForKey:@"sprites"]) {
|
||||
NSDictionary *sprite = [page valueForKey:spriteName];
|
||||
[sprites setValue:sprite forKey:[sprite valueForKey:@"md5"]];
|
||||
}
|
||||
// check thumbnail or create
|
||||
if (![fileManager fileExistsAtPath:[[IO getpath] stringByAppendingPathComponent:pngName]]) {
|
||||
NSString *js = [NSString stringWithFormat:@"ScratchJr.makeThumb('%@', %@, %@);", fileName, [asset valueForKey:@"width"], [asset valueForKey:@"height"]];
|
||||
[ViewController.webview evaluateJavaScript:js completionHandler:nil];
|
||||
}
|
||||
|
||||
// read project data
|
||||
// create project
|
||||
NSDirectoryEnumerator<NSString *> * enumerator = [fileManager enumeratorAtPath:tempDir];
|
||||
NSString *path;
|
||||
while ((path = [enumerator nextObject]) != nil) {
|
||||
// only copy image and sounds
|
||||
if (![path hasSuffix:@".png"] && ![path hasSuffix:@".wav"] && ![path hasSuffix:@".svg"]) {
|
||||
continue;
|
||||
}
|
||||
NSString *fileName = [path lastPathComponent];
|
||||
// NSLog(@"%@", path);
|
||||
NSArray *parts = [path componentsSeparatedByString:@"/"];
|
||||
if (parts.count < 2) {
|
||||
continue;
|
||||
}
|
||||
NSString *folder = parts[1];
|
||||
// extract files
|
||||
NSString *toPath = [[IO getpath] stringByAppendingPathComponent:fileName];
|
||||
if (![fileManager fileExistsAtPath: toPath]) {
|
||||
NSLog(@"copy file to path %@", toPath);
|
||||
NSString *fromPath = [tempDir stringByAppendingString:path];
|
||||
[fileManager copyItemAtPath:fromPath toPath:toPath error:&error];
|
||||
if (error != nil) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ([folder isEqualToString:@"sounds"] || [folder isEqualToString:@"thumbnails"]) {
|
||||
// process for sounds and thumbnails is done
|
||||
continue;
|
||||
}
|
||||
// save background or shape to database.
|
||||
NSString *table = [folder isEqualToString:@"characters"] ? @"usershapes" : @"userbkgs";
|
||||
NSMutableArray *values = [[NSMutableArray alloc] init];
|
||||
[values addObject:fileName];
|
||||
// check database
|
||||
NSString *stmt = [NSString stringWithFormat:@"SELECT id FROM %@ WHERE md5 = ?", table];
|
||||
NSArray *res = [Database findDataIn:stmt with:values];
|
||||
if (res.count > 0) {
|
||||
continue;
|
||||
}
|
||||
// insert into database
|
||||
NSLog(@"%@ not exists, creating", fileName);
|
||||
NSMutableDictionary *asset = [[NSMutableDictionary alloc] init];
|
||||
|
||||
[asset setValue:@"iOSv01" forKey:@"version"];
|
||||
[asset setValue:nil forKey:@"altmd5"];
|
||||
[asset setValue:fileName forKey:@"md5"];
|
||||
[asset setValue:[fileName pathExtension] forKey:@"ext"];
|
||||
[asset setValue:@"480" forKey:@"width"];
|
||||
[asset setValue:@"360" forKey:@"height"];
|
||||
|
||||
if ([folder isEqualToString:@"characters"]) {
|
||||
// create shape
|
||||
NSDictionary *sprite = [sprites valueForKey:fileName];
|
||||
if (sprite == nil) {
|
||||
continue;
|
||||
}
|
||||
NSString *width = [sprite valueForKey:@"w"];
|
||||
NSString *height = [sprite valueForKey:@"h"];
|
||||
[asset setValue:[NSString stringWithFormat:@"%@", width] forKey:@"width"];
|
||||
[asset setValue:[NSString stringWithFormat:@"%@", height] forKey:@"height"];
|
||||
[asset setValue:[sprite valueForKey:@"scale"] forKey:@"scale"];
|
||||
[asset setValue:[sprite valueForKey:@"id"] forKey:@"name"];
|
||||
}
|
||||
[Database insert:table with:asset];
|
||||
}
|
||||
// delete temp folder
|
||||
[fileManager removeItemAtPath:tempDir error:nil];
|
||||
// refresh lobby
|
||||
[ViewController.webview evaluateJavaScript:@"Lobby.refresh();" completionHandler:nil];
|
||||
});
|
||||
[Database insert:table with:asset];
|
||||
}
|
||||
// delete temp folder
|
||||
[fileManager removeItemAtPath:tempDir error:nil];
|
||||
// refresh lobby
|
||||
[ViewController.webview evaluateJavaScript:@"Lobby.refresh();" completionHandler:nil];
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
|
|
|
@ -167,4 +167,7 @@
|
|||
+ (NSString *)stopfeed;
|
||||
+ (NSString *)choosecamera:(NSString *)body;
|
||||
+ (NSString *)captureimage:(NSString *)onCameraCaptureComplete;
|
||||
|
||||
// Imports
|
||||
+ (void) receiveProject:(NSURL *) url;
|
||||
@end
|
||||
|
|
|
@ -6,6 +6,10 @@ CameraView* cameraView;
|
|||
CameraMask* cameraMask;
|
||||
NSString *cameraAvailable;
|
||||
|
||||
// prepare for opening multiple files
|
||||
NSMutableArray *zipUrls;
|
||||
bool appReady = false;
|
||||
|
||||
AVCaptureVideoPreviewLayer* captureVideoPreviewLayer;
|
||||
|
||||
@implementation ScratchJr : NSObject
|
||||
|
@ -16,15 +20,41 @@ NSString *oncomplete;
|
|||
// Init functions
|
||||
/////////////////////////
|
||||
|
||||
|
||||
+ (NSString *) hideSplash :(NSString *)body{
|
||||
UIImageView* splashScreen = [ViewController splashScreen];
|
||||
appReady = true;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[splashScreen removeFromSuperview];
|
||||
});
|
||||
// import projects
|
||||
if (zipUrls != nil && zipUrls.count > 0) {
|
||||
for (int i = 0; i < zipUrls.count; i++) {
|
||||
NSURL *url = zipUrls[i];
|
||||
[zipUrls removeObjectAtIndex:i];
|
||||
[ScratchJr importProject:url];
|
||||
}
|
||||
}
|
||||
return @"1";
|
||||
}
|
||||
|
||||
+ (void) receiveProject:(NSURL *)url {
|
||||
if (zipUrls == nil) {
|
||||
zipUrls = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (appReady) {
|
||||
[ScratchJr importProject:url];
|
||||
} else {
|
||||
[zipUrls addObject:url];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) importProject:(NSURL *) url {
|
||||
NSLog(@"importing project at %@", url.absoluteString);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[IO receiveProject:url];
|
||||
});
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// camera open and close
|
||||
/////////////////////////
|
||||
|
|
|
@ -161,30 +161,6 @@ NSDate *startDate;
|
|||
startDate = [NSDate date];
|
||||
}
|
||||
|
||||
- (void) receiveProject:(NSString *)project{
|
||||
NSString *callback = [NSString stringWithFormat:@"OS.loadProjectFromSjr('%@');", project];
|
||||
WKWebView *webview = [ViewController webview];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[webview evaluateJavaScript:callback completionHandler:^(id result, NSError * _Nullable error) {
|
||||
if (error != nil) {
|
||||
return;
|
||||
}
|
||||
NSString *res = [NSString stringWithFormat:@"%@", result];
|
||||
if ([res isEqualToString:@"1"]) {
|
||||
// Success
|
||||
return;
|
||||
} else if ([res isEqualToString:@"0"]) {
|
||||
// Processing error
|
||||
return;
|
||||
} else {
|
||||
// Loading the project failed - reschedule for a time when the WebView has hopefully loaded
|
||||
// A little bit roundabout, but simpler than queueing projects to be loaded
|
||||
[self performSelector:@selector(receiveProject:) withObject:project afterDelay:2.0];
|
||||
}
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden{
|
||||
return YES;
|
||||
}
|
||||
|
|
|
@ -902,6 +902,19 @@ export default class ScratchJr {
|
|||
return str;
|
||||
}
|
||||
|
||||
static makeThumb(svgName, width, height) {
|
||||
IO.getAsset(svgName, function (svgDataUrl) {
|
||||
var svgBase64 = svgDataUrl.split(',')[1];
|
||||
var dataurl = IO.getThumbnail(atob(svgBase64), width, height, 120, 90);
|
||||
var pngBase64 = dataurl.split(',')[1];
|
||||
var name = svgName.split('.')[0];
|
||||
OS.setmedianame(pngBase64, name, 'png', function () {
|
||||
// we don't need result here.
|
||||
console.log(`thumbnail for ${svgName} generated.`)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/////////////////
|
||||
//Application on the background
|
||||
|
||||
|
|
Loading…
Reference in a new issue