diff --git a/build.py b/build.py index 055c2ef8..a81bfe34 100755 --- a/build.py +++ b/build.py @@ -168,6 +168,11 @@ else: os.makedirs(outDir) +# run any preBuild commands +for cmd in settings.get('preBuild',[]): + os.system ( cmd ) + + # load main.js, parse, and create main total-conversion-build.user.js main = readfile('main.js') @@ -191,15 +196,6 @@ for fn in glob.glob("plugins/*.user.js"): metafn = fn.replace('.user.js', '.meta.js') saveScriptAndMeta(script, os.path.join(outDir,fn), os.path.join(outDir,metafn)) -def copytree(src, dst, symlinks=False, ignore=None): - for item in os.listdir(src): - s = os.path.join(src, item) - d = os.path.join(dst, item) - if os.path.isdir(s): - shutil.copytree(s, d, symlinks, ignore) - else: - shutil.copy2(s, d) - # if we're building mobile too if buildMobile: if buildMobile not in ['debug','release','copyonly']: @@ -223,13 +219,9 @@ if buildMobile: shutil.copy(os.path.join(outDir,"total-conversion-build.user.js"), "mobile/assets/total-conversion-build.user.js") # copy the user location script into the mobile folder. shutil.copy(os.path.join(outDir,"user-location.user.js"), "mobile/assets/user-location.user.js") - # also copy plugins - try: - os.makedirs("mobile/assets/plugins") - except: - pass - copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins") + shutil.rmtree("mobile/assets/plugins") + shutil.copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins", ignore=shutil.ignore_patterns('*.meta.js', 'force-https*')) if buildMobile != 'copyonly': @@ -242,4 +234,9 @@ if buildMobile: shutil.copy("mobile/bin/IITC_Mobile-%s.apk" % buildMobile, os.path.join(outDir,"IITC_Mobile-%s.apk" % buildMobile) ) +# run any postBuild commands +for cmd in settings.get('postBuild',[]): + os.system ( cmd ) + + # vim: ai si ts=4 sw=4 sts=4 et diff --git a/buildsettings.py b/buildsettings.py index 9735ea9f..986b44e9 100644 --- a/buildsettings.py +++ b/buildsettings.py @@ -2,6 +2,14 @@ # if you want to have custom builds, copy this file to "localbuildsettings.py" and make changes there. +# possible fields: +# resourceBaseUrl - optional - the URL base for external resources (all resources embedded in standard IITC) +# distUrlBase - optional - the base URL to use for update checks +# buildMobild - optional - if set, mobild builds are built with 'ant'. requires the Android SDK and appropriate mobile/local.properties file configured +# preBuild - optional - an array of strings to run as commands, via os.system, before building the scripts +# postBuild - optional - an array of string to run as commands, via os.system, after all builds are complete + + buildSettings = { # local: use this build if you're not modifying external resources # no external resources allowed - they're not needed any more @@ -40,6 +48,7 @@ buildSettings = { } + # defaultBuild - the name of the default build to use if none is specified on the build.py command line # (in here as an example - it only works in localbuildsettings.py) #defaultBuild = 'local' diff --git a/mobile/.gitignore b/mobile/.gitignore index c104ea4e..42e4ba7c 100644 --- a/mobile/.gitignore +++ b/mobile/.gitignore @@ -6,6 +6,6 @@ gen/ libs/ proguard-project.txt local.properties -assets/iitc.js +assets/total-conversion-build.user.js assets/user-location.user.js assets/plugins/ diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml index 460d70f3..51f57ac3 100644 --- a/mobile/AndroidManifest.xml +++ b/mobile/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="17" + android:versionName="0.3.5" > + + Reload IITC Print Version Clear Cache + Toggle fullscreen Get Location local close @@ -37,6 +38,8 @@ Nice for tablets, looks awful on smartphones Display user location Show users position on map + Force https + Disabling may improve performance Developer options Enable developer mode If enabled, all IITC sources will be loaded from external storage of the Android device. diff --git a/mobile/res/xml/preferences.xml b/mobile/res/xml/preferences.xml index 432b0eab..c667e8f0 100644 --- a/mobile/res/xml/preferences.xml +++ b/mobile/res/xml/preferences.xml @@ -36,6 +36,11 @@ android:key="pref_plugins" android:title="@string/pref_plugins" android:dialogTitle="@string/pref_plugins_title"/> + - iitc_view.getRootView().getHeight()/3) { + Rect r = new Rect(); + //r will be populated with the coordinates of your view that area still visible. + iitc_view.getWindowVisibleDisplayFrame(r); + + int screenHeight = iitc_view.getRootView().getHeight(); + int heightDiff = screenHeight - (r.bottom - r.top); + boolean visible = heightDiff > screenHeight / 3; + if (visible == true) { Log.d("iitcm", "Open Keyboard..."); IITC_Mobile.this.keyboad_open = true; } else { @@ -114,7 +123,6 @@ public class IITC_Mobile extends Activity { } } else { - Log.d("iitcm", "no intent...loading " + intel_url); this.loadUrl(intel_url); } } @@ -127,6 +135,7 @@ public class IITC_Mobile extends Activity { Log.d("iitcm", "resuming...setting reset idleTimer"); iitc_view.loadUrl("javascript: window.idleTime = 0"); iitc_view.loadUrl("javascript: window.renderUpdateStatus()"); + iitc_view.updateCaching(); if (user_loc == true) { // Register the listener with the Location Manager to receive location updates @@ -181,6 +190,17 @@ public class IITC_Mobile extends Activity { // we want a self defined behavior for the back button @Override public void onBackPressed() { + // leave fullscreen mode if it is enabled + if (fullscreen_mode) { + // get back action bar + this.getActionBar().show(); + // show notification bar again + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.flags ^= WindowManager.LayoutParams.FLAG_FULLSCREEN; + this.getWindow().setAttributes(attrs); + this.fullscreen_mode = false; + return; + } if (this.back_button_pressed) { super.onBackPressed(); return; @@ -219,6 +239,29 @@ public class IITC_Mobile extends Activity { iitc_view.clearFormData(); iitc_view.clearCache(true); return true; + // toggle fullscreen + case R.id.toggle_fullscreen: + if (!this.fullscreen_mode) { + // get rid of action bar + this.getActionBar().hide(); + // hide notification bar + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.flags ^= WindowManager.LayoutParams.FLAG_FULLSCREEN; + this.getWindow().setAttributes(attrs); + this.fullscreen_mode = true; + // show a little toast for the user + Toast.makeText(this, "Press back button to exit fullscreen", Toast.LENGTH_SHORT).show(); + } + else { + // get back action bar + this.getActionBar().show(); + // show notification bar again + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.flags ^= WindowManager.LayoutParams.FLAG_FULLSCREEN; + this.getWindow().setAttributes(attrs); + this.fullscreen_mode = false; + } + return true; // get the users current location and focus it on map case R.id.locate: iitc_view.loadUrl("javascript: window.map.locate({setView : true, maxZoom: 13});"); @@ -259,9 +302,8 @@ public class IITC_Mobile extends Activity { // plugins are injected onPageFinished public void loadUrl(String url) { url = addUrlParam(url); - Log.d("iitcm", "injecting js..."); + Log.d("iitcm", "injecting main-script..."); injectJS(); - Log.d("iitcm", "loading url: " + url); iitc_view.loadUrl(url); } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java b/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java index a5684005..8813b2a7 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java @@ -29,32 +29,30 @@ public class IITC_Settings extends Activity { ArrayList asset_values = new ArrayList(); for (int i = 0; i < asset_array.length ; i++) { - if (asset_array[i].endsWith("user.js")) { - // find user plugin name for user readable entries - Scanner s = null; - String src = ""; - try { - s = new Scanner(am.open("plugins/" + asset_array[i])).useDelimiter("\\A"); - } catch (IOException e2) { - // TODO Auto-generated catch block - e2.printStackTrace(); - } - if (s != null) src = s.hasNext() ? s.next() : ""; - String header = src.substring(src.indexOf("==UserScript=="), src.indexOf("==/UserScript==")); - // remove new line comments and replace with space - // this way we get double spaces instead of newline + double slash - header = header.replace("\n//", " "); - // get a list of key-value...split on multiple spaces - String[] attributes = header.split(" +"); - String plugin_name = "not found"; - for (int j = 0; j < attributes.length; j++) { - // search for name and use the value - if (attributes[j].equals("@name")) plugin_name = attributes[j+1]; - } - asset_list.add(plugin_name); - // real value - asset_values.add(asset_array[i]); + // find user plugin name for user readable entries + Scanner s = null; + String src = ""; + try { + s = new Scanner(am.open("plugins/" + asset_array[i])).useDelimiter("\\A"); + } catch (IOException e2) { + // TODO Auto-generated catch block + e2.printStackTrace(); } + if (s != null) src = s.hasNext() ? s.next() : ""; + String header = src.substring(src.indexOf("==UserScript=="), src.indexOf("==/UserScript==")); + // remove new line comments and replace with space + // this way we get double spaces instead of newline + double slash + header = header.replace("\n//", " "); + // get a list of key-value...split on multiple spaces + String[] attributes = header.split(" +"); + String plugin_name = "not found"; + for (int j = 0; j < attributes.length; j++) { + // search for name and use the value + if (attributes[j].equals("@name")) plugin_name = attributes[j+1]; + } + asset_list.add(plugin_name); + // real value + asset_values.add(asset_array[i]); } Bundle bundle = getIntent().getExtras(); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java index ab9eb115..ba705db9 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java @@ -2,7 +2,12 @@ package com.cradle.iitc_mobile; import android.annotation.SuppressLint; import android.content.Context; +import android.content.SharedPreferences; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.preference.PreferenceManager; import android.util.AttributeSet; +import android.util.Log; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; @@ -22,9 +27,10 @@ public class IITC_WebView extends WebView { settings.setDomStorageEnabled(true); settings.setAllowFileAccess(true); settings.setGeolocationEnabled(true); + settings.setAppCacheEnabled(true); settings.setDatabasePath(this.getContext().getApplicationInfo().dataDir + "/databases/"); - settings.setAppCachePath(this.getContext().getApplicationInfo().dataDir + "/cache/"); - settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); + settings.setAppCachePath(this.getContext().getCacheDir().getAbsolutePath()); + // use cache if on mobile network...saves traffic this.js_interface = new IITC_JSInterface(c); this.addJavascriptInterface(js_interface, "android"); @@ -61,6 +67,20 @@ public class IITC_WebView extends WebView { } //---------------------------------------------------------------- + @Override + public void loadUrl(String url) { + if (!url.startsWith("javascript:")) { + // force https if enabled in settings + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext()); + if (sharedPref.getBoolean("pref_force_https", true)) + url = url.replace("http://", "https://"); + else + url = url.replace("https://", "http://"); + Log.d("iitcm", "loading url: " + url); + } + super.loadUrl(url); + } + public IITC_WebViewClient getWebViewClient() { return this.webclient; } @@ -69,4 +89,21 @@ public class IITC_WebView extends WebView { return this.js_interface; } + public void updateCaching() { + if (!this.isConnectedToWifi()) + { + Log.d("iitcm", "not connected to wifi...load tiles from cache"); + settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); + } else { + Log.d("iitcm", "connected to wifi...load tiles from network"); + settings.setCacheMode(WebSettings.LOAD_DEFAULT); + } + } + + private boolean isConnectedToWifi() { + ConnectivityManager conMan = (ConnectivityManager) getContext().getSystemService( Context.CONNECTIVITY_SERVICE ); + NetworkInfo wifi = conMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + return wifi.getState() == NetworkInfo.State.CONNECTED; + } + } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index 60f428c5..c75f538b 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -17,7 +17,7 @@ import android.widget.Toast; import java.io.ByteArrayInputStream; import java.io.File; -import java.io.InputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; import java.util.Scanner; @@ -30,13 +30,12 @@ public class IITC_WebViewClient extends WebViewClient { private WebResourceResponse iitcjs; private String js = null; - private String dev_path = null; + private String iitc_path = null; Context context; public IITC_WebViewClient(Context c) { this.context = c; - this.dev_path = Environment.getExternalStorageDirectory().getPath() + - "/IITC_Mobile/dev/"; + this.iitc_path = Environment.getExternalStorageDirectory().getPath() + "/IITC_Mobile/"; try { loadIITC_JS(c); } catch(IOException e) { @@ -68,32 +67,24 @@ public class IITC_WebViewClient extends WebViewClient { String js = ""; // if developer mode are enabled, load all iitc script from external storage - if (sharedPref.getBoolean("pref_dev_checkbox", true)) { - File js_file = new File(dev_path + "total-conversion-build.user.js"); - if (!js_file.exists()) { - Toast.makeText(context, "File " + dev_path + - "total-conversion-build.user.js not found. " + + if (sharedPref.getBoolean("pref_dev_checkbox", false)) { + js = this.fileToString(iitc_path + "dev/total-conversion-build.user.js", false); + if (js.equals("false")) { + Toast.makeText(context, "File " + iitc_path + + "dev/total-conversion-build.user.js not found. " + "Disable developer mode or add iitc files " + "to the dev folder.", Toast.LENGTH_LONG).show(); + return; } else { Toast.makeText(context, "Developer mode enabled", Toast.LENGTH_SHORT).show(); } - Scanner s = null; - s = new Scanner(js_file).useDelimiter("\\A"); - if (s != null) js = s.hasNext() ? s.next() : ""; } else { // load iitc script from web or asset folder if (iitc_source.contains("http")) { URL url = new URL(iitc_source); js = new Scanner(url.openStream(), "UTF-8").useDelimiter("\\A").next(); } else { - InputStream input; - input = c.getAssets().open("total-conversion-build.user.js"); - int size = input.available(); - byte[] buffer = new byte[size]; - input.read(buffer); - input.close(); - js = new String(buffer); + js = this.fileToString("total-conversion-build.user.js", true); } } @@ -131,59 +122,83 @@ public class IITC_WebViewClient extends WebViewClient { // iterate through all enabled plugins and load them if (plugin_list != null) { - AssetManager am = context.getAssets(); String[] plugin_array = plugin_list.toArray(new String[0]); for(int i = 0; i < plugin_list.size(); i++) { - if (plugin_array[i].endsWith("user.js")); - { - Log.d("iitcm", "adding plugin " + plugin_array[i]); - Scanner s = null; - String src = ""; - try { - // load plugins from external storage if dev mode are enabled - if (dev_enabled) { - File js_file = new File(dev_path + "plugins/" + plugin_array[i]); - s = new Scanner(js_file).useDelimiter("\\A"); - } - else - // load plugins from asset folder - s = new Scanner(am.open("plugins/" + plugin_array[i])).useDelimiter("\\A"); - } catch (IOException e2) { - // TODO Auto-generated catch block - e2.printStackTrace(); - } - if (s != null) src = s.hasNext() ? s.next() : ""; - view.loadUrl("javascript:" + src); - } + Log.d("iitcm", "adding plugin " + plugin_array[i]); + if (dev_enabled) + this.loadJS(iitc_path + "dev/plugins/" + plugin_array[i], false, view); + else + this.loadJS("plugins/" + plugin_array[i], true, view); } } // inject the user location script if enabled in settings if (sharedPref.getBoolean("pref_user_loc", false)) enableTracking(view, dev_enabled); + + // load additional plugins from /IITC-Mobile/plugins/ + File directory = new File(iitc_path + "plugins/"); + File[] files = directory.listFiles(); + if (files != null) { + for (int i = 0; i < files.length; ++i) { + if(this.loadJS(files[i].toString(), false, view)) + Log.d("iitcm", "loading additional plugin " + files[i].toString()); + } + } } public void enableTracking(WebView view, boolean dev_enabled) { Log.d("iitcm", "enable tracking..."); - AssetManager am = context.getAssets(); - Scanner s = null; - String src = ""; - try { // load plugin from external storage if dev mode are enabled - if (dev_enabled) { - File js_file = new File(dev_path + "user-location.user.js"); - s = new Scanner(js_file).useDelimiter("\\A"); - } + if (dev_enabled) + this.loadJS(iitc_path + "dev/user-location.user.js", false, view); else // load plugin from asset folder - s = new Scanner(am.open("user-location.user.js")).useDelimiter("\\A"); - } catch (IOException e2) { - // TODO Auto-generated catch block - e2.printStackTrace(); + this.loadJS("user-location.user.js", true, view); + } + + // read a file into a string + // use the full path for File + // if asset == true use the asset manager to open file + public String fileToString(String file, boolean asset) { + Scanner s = null; + String src= ""; + if (!asset) { + File js_file = new File(file); + try { + s = new Scanner(js_file).useDelimiter("\\A"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + Log.d("iitcm", "failed to parse file " + file); + return "false"; + } + } else { + // load plugins from asset folder + AssetManager am = context.getAssets(); + try { + s = new Scanner(am.open(file)).useDelimiter("\\A"); + } catch (IOException e) { + e.printStackTrace(); + Log.d("iitcm", "failed to parse file assets/" + file); + return "false"; + } } + if (s != null) src = s.hasNext() ? s.next() : ""; - view.loadUrl("javascript:" + src); + return src; + } + + // read a file into a string + // load it as javascript + public boolean loadJS(String file, boolean asset, WebView view) { + if (!file.endsWith("user.js")) + return false; + String js = fileToString(file, asset); + if (js.equals("false")) + return false; + else view.loadUrl("javascript:" + js); + return true; } // Check every external resource if it’s okay to load it and maybe replace it @@ -227,4 +242,4 @@ public class IITC_WebViewClient extends WebViewClient { return true; } } -} +} \ No newline at end of file diff --git a/website/index.php b/website/index.php index 2e3ee02d..559bd540 100644 --- a/website/index.php +++ b/website/index.php @@ -86,7 +86,9 @@ $pages = Array ( 'donate' => ' Donate', ); -$page = $_REQUEST['page']; +$page = 'home'; +if ( array_key_exists ( 'page', $_REQUEST ) ) + $page = $_REQUEST['page']; if ( ! array_key_exists ( $page, $pages ) ) $page = "home"; diff --git a/website/page/code/mobile-download.php b/website/page/code/mobile-download.php index 9a15e8de..5da156a6 100644 --- a/website/page/code/mobile-download.php +++ b/website/page/code/mobile-download.php @@ -17,15 +17,21 @@ function getMobileVersion ( $apkfile ) $archive = $apkinfo->getApkArchive(); - $iitc_file = "assets/total-conversion-build.user.js"; - if ( $archive->statName ( $iitc_file ) === FALSE ); - $iitc_file = "assets/iitc.js"; - $stream = $archive->getStream ( $iitc_file ); + $stream = $archive->getStream ( "assets/total-conversion-build.user.js" ); + if ( ! $stream ) + $stream = $archive->getStream ( "assets/iitc.js" ); - $header = loadUserScriptHeader ( $stream ); + if ( $stream ) + { + $header = loadUserScriptHeader ( $stream ); - $result['iitc_version'] = $header['@version']; + $result['iitc_version'] = $header['@version']; + } + else + { + $result['iitc_version'] = 'unknown'; + } return $result; } @@ -40,7 +46,7 @@ function iitcMobileDownload ( $apkfile ) # we need an absolute link for the QR Code # get the URL of this page itself - $pageurl = ($_SERVER['HTTPS'] ? "https" : "http")."://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; + $pageurl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] ? "https" : "http")."://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; $apkurl = url_to_absolute ( $pageurl, $apkfile ); ?> diff --git a/website/page/code/userscript.php b/website/page/code/userscript.php index c229df76..845cc116 100644 --- a/website/page/code/userscript.php +++ b/website/page/code/userscript.php @@ -26,7 +26,7 @@ function loadUserScriptHeader($file) } } - fclose ( $f ); + fclose ( $file ); return $result; } diff --git a/website/page/test.php b/website/page/test.php index c91bdee0..db491779 100644 --- a/website/page/test.php +++ b/website/page/test.php @@ -19,10 +19,13 @@ include_once ( "code/desktop-download.php" ); $path = "test"; -if ( $_REQUEST['build'] == 'experimental' ) - $path = "experimental"; -if ( $_REQUEST['build'] == 'dev' ) - $path = "dev"; +if ( array_key_exists ( 'build', $_REQUEST ) ) +{ + if ( $_REQUEST['build'] == 'experimental' ) + $path = "experimental"; + if ( $_REQUEST['build'] == 'dev' ) + $path = "dev"; +} if ( $path != "test" ) print "
NOTE: A non-standard test build, $path, is currently selected. The notes may not apply! Return to the standard test build.
";