diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..412eeda7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/build.py b/build.py index a81bfe34..8cf81b1e 100755 --- a/build.py +++ b/build.py @@ -220,6 +220,10 @@ if buildMobile: # 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 shutil.rmtree("mobile/assets/plugins") shutil.copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins", ignore=shutil.ignore_patterns('*.meta.js', 'force-https*')) diff --git a/code/boot.js b/code/boot.js index 3ad6790d..db2411b9 100644 --- a/code/boot.js +++ b/code/boot.js @@ -3,6 +3,8 @@ // created a basic framework. All of these functions should only ever // be run once. +// Used to disable on multitouch devices +window.showZoom = true; window.setupBackButton = function() { var c = window.isSmartphone() @@ -156,7 +158,7 @@ window.setupMap = function() { window.map = new L.Map('map', $.extend(getPosition(), - {zoomControl: true} + {zoomControl: window.showZoom} )); var addLayers = {}; @@ -169,20 +171,20 @@ window.setupMap = function() { var t = (i === 0 ? 'Unclaimed' : 'Level ' + i) + ' Portals'; addLayers[t] = portalsLayers[i]; // Store it in hiddenLayer to remove later - if(!isLayerGroupDisplayed(t)) hiddenLayer.push(portalsLayers[i]); + if(!isLayerGroupDisplayed(t, true)) hiddenLayer.push(portalsLayers[i]); } fieldsLayer = L.layerGroup([]); map.addLayer(fieldsLayer, true); addLayers['Fields'] = fieldsLayer; // Store it in hiddenLayer to remove later - if(!isLayerGroupDisplayed('Fields')) hiddenLayer.push(fieldsLayer); + if(!isLayerGroupDisplayed('Fields', true)) hiddenLayer.push(fieldsLayer); linksLayer = L.layerGroup([]); map.addLayer(linksLayer, true); addLayers['Links'] = linksLayer; // Store it in hiddenLayer to remove later - if(!isLayerGroupDisplayed('Links')) hiddenLayer.push(linksLayer); + if(!isLayerGroupDisplayed('Links', true)) hiddenLayer.push(linksLayer); window.layerChooser = new L.Control.Layers({ 'MapQuest OSM': views[0], @@ -236,8 +238,8 @@ window.setupMap = function() { map.on('moveend zoomend', function() { window.mapRunsUserAction = false }); // update map hooks - map.on('movestart zoomstart', window.requests.abort); - map.on('moveend zoomend', function() { console.log('map moveend'); window.startRefreshTimeout(ON_MOVE_REFRESH*1000) }); + map.on('movestart zoomstart', function() { window.requests.abort(); window.startRefreshTimeout(-1); }); + map.on('moveend zoomend', function() { window.startRefreshTimeout(ON_MOVE_REFRESH*1000) }); window.addResumeFunction(window.requestData); window.requests.addRefreshFunction(window.requestData); diff --git a/code/chat.js b/code/chat.js index a2b78797..bfc53859 100644 --- a/code/chat.js +++ b/code/chat.js @@ -473,16 +473,14 @@ window.chat.needMoreMessages = function() { chat.requestPublic(true); } - -window.chat.chooser = function(event) { - var t = $(event.target); +window.chat.chooseAnchor = function(t) { var tt = t.text(); var mark = $('#chatinput mark'); var input = $('#chatinput input'); $('#chatcontrols .active').removeClass('active'); - t.addClass('active'); + $("#chatcontrols a:contains('" + tt + "')").addClass('active'); $('#chat > div').hide(); @@ -520,10 +518,23 @@ window.chat.chooser = function(event) { elm.scrollTop(elm.data('needsScrollTop')); elm.data('needsScrollTop', null); } - - chat.needMoreMessages(); } +window.chat.show = function(name) { + window.isSmartphone + ? $('#updatestatus').hide() + : $('#updatestatus').show(); + $('#chat, #chatinput').show(); + $('#map').css('visibility', 'hidden'); + + var t = $(''+name+''); + window.chat.chooseAnchor(t); +} + +window.chat.chooser = function(event) { + var t = $(event.target); + window.chat.chooseAnchor(t); +} // contains the logic to keep the correct scroll position. window.chat.keepScrollPosition = function(box, scrollBefore, isOldMsgs) { diff --git a/code/debugging.js b/code/debugging.js index 8c40a155..e1d92d56 100644 --- a/code/debugging.js +++ b/code/debugging.js @@ -48,16 +48,23 @@ window.debug.console = function() { $('#debugconsole').text(); } -window.debug.console.create = function() { - if($('#debugconsole').length) return; - $('#chatcontrols').append('debug'); - $('#chatcontrols a:last').click(function() { +window.debug.console.show = function() { + $('#scrollwrapper, #updatestatus').hide(); + // not displaying the map causes bugs in Leaflet + $('#map').css('visibility', 'hidden'); + $('#chat, #chatinput').show(); + window.debug.console.create(); $('#chatinput mark').css('cssText', 'color: #bbb !important').text('debug:'); $('#chat > div').hide(); $('#debugconsole').show(); $('#chatcontrols .active').removeClass('active'); - $(this).addClass('active'); - }); + $("#chatcontrols a:contains('debug')").addClass('active'); +} + +window.debug.console.create = function() { + if($('#debugconsole').length) return; + $('#chatcontrols').append('debug'); + $('#chatcontrols a:last').click(window.debug.console.show); $('#chat').append(''); } diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js index 205b80c5..0f02d879 100644 --- a/code/portal_detail_display.js +++ b/code/portal_detail_display.js @@ -95,9 +95,16 @@ window.setPortalIndicators = function(d) { ).addTo(map); else portalAccessIndicator.setLatLng(coord); - } +window.clearPortalIndicators = function() { + if(portalRangeIndicator) map.removeLayer(portalRangeIndicator); + portalRangeIndicator = null; + if(portalAccessIndicator) map.removeLayer(portalAccessIndicator); + portalAccessIndicator = null; +} + + // highlights portal with given GUID. Automatically clears highlights // on old selection. Returns false if the selected portal changed. // Returns true if it’s still the same portal that just needs an @@ -123,4 +130,5 @@ window.unselectOldPortal = function() { if(oldPortal) portalResetColor(oldPortal); selectedPortal = null; $('#portaldetails').html(''); + clearPortalIndicators(); } diff --git a/code/request_handling.js b/code/request_handling.js index 84617d54..8b6c3ce7 100644 --- a/code/request_handling.js +++ b/code/request_handling.js @@ -38,6 +38,7 @@ window.requests.abort = function() { // gives user feedback about pending operations. Draws current status // to website. Updates info in layer chooser. window.renderUpdateStatus = function() { + var t = 'map status: '; if(mapRunsUserAction) t += 'paused during interaction'; @@ -48,7 +49,7 @@ window.renderUpdateStatus = function() { else if(window.requests._quickRefreshPending) t += 'refreshing...'; else - t += 'Up to date.'; + t += 'Up to date. '; if(renderLimitReached()) t += ' RENDER LIMIT ' @@ -82,6 +83,8 @@ window.startRefreshTimeout = function(override) { // status bar window.renderUpdateStatus(); if(refreshTimeout) clearTimeout(refreshTimeout); + if(override == -1) return; //don't set a new timeout + var t = 0; if(override) { window.requests._quickRefreshPending = true; diff --git a/code/smartphone.js b/code/smartphone.js index 3162b6d5..cdbabc4f 100644 --- a/code/smartphone.js +++ b/code/smartphone.js @@ -34,20 +34,12 @@ window.runOnSmartphonesBeforeBoot = function() { + ''); } - // this also matches the expand button, but it is hidden via CSS - $('#chatcontrols a').click(function() { - $('#scrollwrapper, #updatestatus').hide(); - // not displaying the map causes bugs in Leaflet - $('#map').css('visibility', 'hidden'); - $('#chat, #chatinput').show(); - }); - window.smartphone.mapButton = $('map').click(function() { $('#chat, #chatinput, #scrollwrapper').hide(); $('#map').css('visibility', 'visible'); $('#updatestatus').show(); - $('.active').removeClass('active'); - $(this).addClass('active'); + $('#chatcontrols a .active').removeClass('active'); + $("#chatcontrols a:contains('map')").addClass('active'); }); window.smartphone.sideButton = $('info').click(function() { @@ -55,7 +47,7 @@ window.runOnSmartphonesBeforeBoot = function() { $('#map').css('visibility', 'hidden'); $('#scrollwrapper').show(); $('.active').removeClass('active'); - $(this).addClass('active'); + $("#chatcontrols a:contains('info')").addClass('active'); }); $('#chatcontrols').append(smartphone.mapButton).append(smartphone.sideButton); @@ -80,7 +72,6 @@ window.runOnSmartphonesAfterBoot = function() { if(!isSmartphone()) return; console.warn('running smartphone post boot stuff'); - chat.toggle(); smartphone.mapButton.click(); // disable img full view diff --git a/code/window_management.js b/code/window_management.js new file mode 100644 index 00000000..8da89133 --- /dev/null +++ b/code/window_management.js @@ -0,0 +1,30 @@ +// created to start cleaning up "window" interaction +// +window.show = function(id) { + switch(id) { + case 'full': + window.chat.show('full'); + break; + case 'compact': + window.chat.show('compact'); + break; + case 'public': + window.chat.show('public'); + break; + case 'faction': + window.chat.show('faction'); + break; + case 'debug': + window.debug.console.show(); + break; + case 'map': + window.smartphone.mapButton.click(); + break; + case 'info': + window.smartphone.sideButton.click(); + break; + default: + window.smartphone.mapButton.click(); + break; + } +} diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml index 51f57ac3..8249bf42 100644 --- a/mobile/AndroidManifest.xml +++ b/mobile/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="18" + android:versionName="0.3.6" > + android:theme="@style/AppTheme" android:uiOptions="splitActionBarWhenNarrow"> + android:orientation="vertical"> - - + + + + + + + + + + + + + + + + + + + + - - - - - - + + - + android:title="@string/action_settings"> + + + + + \ No newline at end of file diff --git a/mobile/res/values/strings.xml b/mobile/res/values/strings.xml index 28905280..9316a1f0 100644 --- a/mobile/res/values/strings.xml +++ b/mobile/res/values/strings.xml @@ -18,7 +18,7 @@ Ingress Intel Total Conversion Mobile

- by cradle

+ by cradle and contributors

Icon by Giuseppe Lucido

IITC Mobile is an optimized mobile browser for the Ingress Intel Total Conversion (IITC) userscript by breunigs. @@ -34,10 +34,12 @@ Misc Plugins Available plugins - Force desktop mode - Nice for tablets, looks awful on smartphones Display user location Show users position on map + Show zoom control + Shows +/- buttons even on multitouch capable devices. + Hide Action Bar in fullscreen mode + Nice for screenshots. Note: IITCM cannot be controlled without Action Bar. Force https Disabling may improve performance Developer options @@ -46,4 +48,12 @@ Please copy all sources from $IITC_folder/build/mobile/ to /sdcard/IITC_Mobile/dev/.
IITC source + Chat + Map + Full + Compact + Public + Faction + Info + Debug \ No newline at end of file diff --git a/mobile/res/xml/preferences.xml b/mobile/res/xml/preferences.xml index c667e8f0..f986bc1e 100644 --- a/mobile/res/xml/preferences.xml +++ b/mobile/res/xml/preferences.xml @@ -12,17 +12,22 @@ - - + + + screenHeight / 3; - if (visible == true) { - Log.d("iitcm", "Open Keyboard..."); - IITC_Mobile.this.keyboad_open = true; - } else { - Log.d("iitcm", "Close Keyboard..."); - IITC_Mobile.this.keyboad_open = false; - } - } - }); + 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 { + Log.d("iitcm", "Close Keyboard..."); + IITC_Mobile.this.keyboad_open = false; + } + } + }); // Acquire a reference to the system Location Manager - loc_mngr = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); + loc_mngr = (LocationManager) this + .getSystemService(Context.LOCATION_SERVICE); // Define a listener that responds to location updates loc_listener = new LocationListener() { public void onLocationChanged(Location location) { - // Called when a new location is found by the network location provider. - drawMarker(location); + // Called when a new location is found by the network location + // provider. + drawMarker(location); } - public void onStatusChanged(String provider, int status, Bundle extras) {} + public void onStatusChanged(String provider, int status, + Bundle extras) { + } - public void onProviderEnabled(String provider) {} + public void onProviderEnabled(String provider) { + } - public void onProviderDisabled(String provider) {} - }; + public void onProviderDisabled(String provider) { + } + }; user_loc = sharedPref.getBoolean("pref_user_loc", false); if (user_loc == true) { - // Register the listener with the Location Manager to receive location updates - loc_mngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, loc_listener); - loc_mngr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, loc_listener); + // Register the listener with the Location Manager to receive + // location updates + loc_mngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, + 0, 0, loc_listener); + loc_mngr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, + loc_listener); } + fullscreen_actionbar = sharedPref.getBoolean("pref_fullscreen_actionbar", false); + // load new iitc web view with ingress intel page Intent intent = getIntent(); String action = intent.getAction(); @@ -121,8 +152,7 @@ public class IITC_Mobile extends Activity { Log.d("iitcm", "loading url..."); this.loadUrl(url); } - } - else { + } else { this.loadUrl(intel_url); } } @@ -138,9 +168,12 @@ public class IITC_Mobile extends Activity { iitc_view.updateCaching(); if (user_loc == true) { - // Register the listener with the Location Manager to receive location updates - loc_mngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, loc_listener); - loc_mngr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, loc_listener); + // Register the listener with the Location Manager to receive + // location updates + loc_mngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, + 0, 0, loc_listener); + loc_mngr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, + loc_listener); } } @@ -148,25 +181,32 @@ public class IITC_Mobile extends Activity { protected void onStop() { ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo mobile = conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); + NetworkInfo mobile = conMan + .getNetworkInfo(ConnectivityManager.TYPE_MOBILE); NetworkInfo wifi = conMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI); // check if Mobile or Wifi module is available..then handle states - // TODO: theory...we do not have to check for a Wifi module...every android device should have one + // TODO: theory...we do not have to check for a Wifi module...every + // android device should have one if (mobile != null) { Log.d("iitcm", "mobile internet module detected...check states"); - if (mobile.getState() == NetworkInfo.State.CONNECTED || mobile.getState() == NetworkInfo.State.CONNECTING) { - Log.d("iitcm", "connected to mobile net...abort all running requests"); + if (mobile.getState() == NetworkInfo.State.CONNECTED + || mobile.getState() == NetworkInfo.State.CONNECTING) { + Log.d("iitcm", + "connected to mobile net...abort all running requests"); // cancel all current requests iitc_view.loadUrl("javascript: window.requests.abort()"); // set idletime to maximum...no need for more iitc_view.loadUrl("javascript: window.idleTime = 999"); - } else if (wifi.getState() == NetworkInfo.State.CONNECTED || wifi.getState() == NetworkInfo.State.CONNECTING) { - iitc_view.loadUrl("javascript: window.idleTime = 999"); + } else if (wifi.getState() == NetworkInfo.State.CONNECTED + || wifi.getState() == NetworkInfo.State.CONNECTING) { + iitc_view.loadUrl("javascript: window.idleTime = 999"); } } else { - Log.d("iitcm", "no mobile internet module detected...check wifi state"); - if (wifi.getState() == NetworkInfo.State.CONNECTED || wifi.getState() == NetworkInfo.State.CONNECTING) { + Log.d("iitcm", + "no mobile internet module detected...check wifi state"); + if (wifi.getState() == NetworkInfo.State.CONNECTED + || wifi.getState() == NetworkInfo.State.CONNECTING) { iitc_view.loadUrl("javascript: window.idleTime = 999"); } } @@ -192,8 +232,8 @@ public class IITC_Mobile extends Activity { public void onBackPressed() { // leave fullscreen mode if it is enabled if (fullscreen_mode) { - // get back action bar - this.getActionBar().show(); + if (fullscreen_actionbar) + this.getActionBar().show(); // show notification bar again WindowManager.LayoutParams attrs = getWindow().getAttributes(); attrs.flags ^= WindowManager.LayoutParams.FLAG_FULLSCREEN; @@ -214,7 +254,7 @@ public class IITC_Mobile extends Activity { new Handler().postDelayed(new Runnable() { @Override public void run() { - back_button_pressed=false; + back_button_pressed = false; } }, 500); } @@ -223,6 +263,7 @@ public class IITC_Mobile extends Activity { public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); + return true; } @@ -230,50 +271,90 @@ public class IITC_Mobile extends Activity { public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { - case R.id.reload_button: - this.loadUrl(intel_url); - return true; - // clear cache - case R.id.cache_clear: - iitc_view.clearHistory(); - 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});"); - return true; - // start settings activity - case R.id.settings: - Intent intent = new Intent(this, IITC_Settings.class); - intent.putExtra("iitc_version", iitc_view.getWebViewClient().getIITCVersion()); - startActivity(intent); - return true; - default: - return super.onOptionsItemSelected(item); + case android.R.id.home : + iitc_view.loadUrl("javascript: window.show('map');"); + actionBar.setTitle(getString(R.string.menu_map)); + return true; + case R.id.menu_map : + iitc_view.loadUrl("javascript: window.show('map');"); + actionBar.setTitle(getString(R.string.menu_map)); + return true; + case R.id.reload_button : + this.loadUrl(intel_url); + actionBar.setTitle(getString(R.string.menu_map)); + return true; + // clear cache + case R.id.cache_clear : + iitc_view.clearHistory(); + iitc_view.clearFormData(); + iitc_view.clearCache(true); + return true; + // toggle fullscreen + case R.id.toggle_fullscreen : + if (!this.fullscreen_mode) { + if (fullscreen_actionbar) + 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 { + if (fullscreen_actionbar) + 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.show('map');"); + iitc_view + .loadUrl("javascript: window.map.locate({setView : true, maxZoom: 13});"); + actionBar.setTitle(getString(R.string.menu_map)); + return true; + // start settings activity + case R.id.action_settings : + Intent intent = new Intent(this, IITC_Settings.class); + intent.putExtra("iitc_version", iitc_view.getWebViewClient() + .getIITCVersion()); + startActivity(intent); + return true; + case R.id.menu_info : + iitc_view.loadUrl("javascript: window.show('info');"); + actionBar.setTitle(getString(R.string.menu_info)); + return true; + case R.id.menu_full : + iitc_view.loadUrl("javascript: window.show('full');"); + actionBar.setTitle(getString(R.string.menu_full)); + return true; + case R.id.menu_compact : + iitc_view.loadUrl("javascript: window.show('compact');"); + actionBar.setTitle(getString(R.string.menu_compact)); + return true; + case R.id.menu_public : + iitc_view.loadUrl("javascript: window.show('public');"); + actionBar.setTitle(getString(R.string.menu_public)); + return true; + case R.id.menu_faction : + iitc_view.loadUrl("javascript: window.show('faction');"); + actionBar.setTitle(getString(R.string.menu_faction)); + return true; + case R.id.menu_debug : + iitc_view.loadUrl("javascript: window.show('debug')"); + actionBar.setTitle(getString(R.string.menu_debug)); + return true; + default : + return super.onOptionsItemSelected(item); } } @@ -287,15 +368,10 @@ public class IITC_Mobile extends Activity { } } - // vp=f enables desktop mode...vp=m is the defaul mobile view + // Force mobile view. + // New actions are not compatible with desktop mode private String addUrlParam(String url) { - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); - this.desktop = sharedPref.getBoolean("pref_force_desktop", false); - - if (desktop) - return (url + "?vp=f"); - else - return (url + "?vp=m"); + return (url + "?vp=m"); } // inject the iitc-script and load the intel url @@ -313,9 +389,9 @@ public class IITC_Mobile extends Activity { // should avoid gps glitches if (loc.getAccuracy() < 100) { if (keyboad_open == false) { - iitc_view.loadUrl("javascript: " + - "window.plugin.userLocation.updateLocation( " + - loc.getLatitude() + ", " + loc.getLongitude() + ");"); + iitc_view.loadUrl("javascript: " + + "window.plugin.userLocation.updateLocation( " + + loc.getLatitude() + ", " + loc.getLongitude() + ");"); } } } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java b/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java index 8813b2a7..f019e2ac 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java @@ -28,18 +28,21 @@ public class IITC_Settings extends Activity { ArrayList asset_list = new ArrayList(); ArrayList asset_values = new ArrayList(); - for (int i = 0; i < asset_array.length ; i++) { + for (int i = 0; i < asset_array.length; 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"); + 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==")); + 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//", " "); @@ -48,7 +51,8 @@ public class IITC_Settings extends Activity { 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]; + if (attributes[j].equals("@name")) + plugin_name = attributes[j + 1]; } asset_list.add(plugin_name); // real value @@ -56,13 +60,14 @@ public class IITC_Settings extends Activity { } Bundle bundle = getIntent().getExtras(); - bundle.putStringArray("ASSETS", (String[]) asset_list.toArray(new String[0])); - bundle.putStringArray("ASSETS_VAL", (String[]) asset_values.toArray(new String[0])); + bundle.putStringArray("ASSETS", + (String[]) asset_list.toArray(new String[0])); + bundle.putStringArray("ASSETS_VAL", + (String[]) asset_values.toArray(new String[0])); settings.setArguments(bundle); // Display the fragment as the main content. getFragmentManager().beginTransaction() - .replace(android.R.id.content, settings) - .commit(); + .replace(android.R.id.content, settings).commit(); } } \ No newline at end of file diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java b/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java index 5a68f307..3859a5f4 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java @@ -23,20 +23,21 @@ public class IITC_SettingsFragment extends PreferenceFragment { addPreferencesFromResource(R.xml.preferences); - //plugins + // plugins MultiSelectListPreference pref_plugins = (MultiSelectListPreference) findPreference("pref_plugins"); pref_plugins.setEntries(getArguments().getStringArray("ASSETS")); - pref_plugins.setEntryValues(getArguments().getStringArray("ASSETS_VAL")); + pref_plugins + .setEntryValues(getArguments().getStringArray("ASSETS_VAL")); // set build version ListPreference pref_build_version = (ListPreference) findPreference("pref_build_version"); PackageManager pm = getActivity().getPackageManager(); String version = "unknown"; try { - PackageInfo info = pm.getPackageInfo(getActivity().getPackageName(), 0); + PackageInfo info = pm.getPackageInfo( + getActivity().getPackageName(), 0); version = info.versionName; - } - catch (NameNotFoundException e) { + } catch (NameNotFoundException e) { e.printStackTrace(); } pref_build_version.setSummary(version); @@ -47,16 +48,20 @@ public class IITC_SettingsFragment extends PreferenceFragment { // set iitc source EditTextPreference pref_iitc_source = (EditTextPreference) findPreference("pref_iitc_source"); - pref_iitc_source.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - preference.setSummary((CharSequence) newValue); - // TODO: update iitc_version when iitc source has changed - return true; - } - }); + pref_iitc_source + .setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, + Object newValue) { + preference.setSummary((CharSequence) newValue); + // TODO: update iitc_version when iitc source has + // changed + return true; + } + }); // first init of summary - String pref_iitc_source_sum = (String) pref_iitc_source.getSummary() + pref_iitc_source.getText(); + String pref_iitc_source_sum = (String) pref_iitc_source.getSummary() + + pref_iitc_source.getText(); pref_iitc_source.setSummary(pref_iitc_source_sum); } } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java index ba705db9..ba63e570 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java @@ -28,8 +28,10 @@ public class IITC_WebView extends WebView { settings.setAllowFileAccess(true); settings.setGeolocationEnabled(true); settings.setAppCacheEnabled(true); - settings.setDatabasePath(this.getContext().getApplicationInfo().dataDir + "/databases/"); - settings.setAppCachePath(this.getContext().getCacheDir().getAbsolutePath()); + settings.setDatabasePath(this.getContext().getApplicationInfo().dataDir + + "/databases/"); + 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"); @@ -38,7 +40,8 @@ public class IITC_WebView extends WebView { // allow access by default this.setWebChromeClient(new WebChromeClient() { @Override - public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { + public void onGeolocationPermissionsShowPrompt(String origin, + GeolocationPermissions.Callback callback) { callback.invoke(origin, true, false); } }); @@ -65,13 +68,15 @@ public class IITC_WebView extends WebView { iitc_init(context); } - //---------------------------------------------------------------- + + // ---------------------------------------------------------------- @Override public void loadUrl(String url) { if (!url.startsWith("javascript:")) { // force https if enabled in settings - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext()); + SharedPreferences sharedPref = PreferenceManager + .getDefaultSharedPreferences(getContext()); if (sharedPref.getBoolean("pref_force_https", true)) url = url.replace("http://", "https://"); else @@ -90,8 +95,7 @@ public class IITC_WebView extends WebView { } public void updateCaching() { - if (!this.isConnectedToWifi()) - { + if (!this.isConnectedToWifi()) { Log.d("iitcm", "not connected to wifi...load tiles from cache"); settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); } else { @@ -101,7 +105,8 @@ public class IITC_WebView extends WebView { } private boolean isConnectedToWifi() { - ConnectivityManager conMan = (ConnectivityManager) getContext().getSystemService( Context.CONNECTIVITY_SERVICE ); + 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 c75f538b..f606d5ac 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -3,6 +3,7 @@ package com.cradle.iitc_mobile; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.net.Uri; import android.net.http.SslError; @@ -25,8 +26,10 @@ import java.util.Set; public class IITC_WebViewClient extends WebViewClient { private static final ByteArrayInputStream style = new ByteArrayInputStream( - "body, #dashboard_container, #map_canvas { background: #000 !important; }".getBytes()); - private static final ByteArrayInputStream empty = new ByteArrayInputStream("".getBytes()); + "body, #dashboard_container, #map_canvas { background: #000 !important; }" + .getBytes()); + private static final ByteArrayInputStream empty = new ByteArrayInputStream( + "".getBytes()); private WebResourceResponse iitcjs; private String js = null; @@ -35,10 +38,11 @@ public class IITC_WebViewClient extends WebViewClient { public IITC_WebViewClient(Context c) { this.context = c; - this.iitc_path = Environment.getExternalStorageDirectory().getPath() + "/IITC_Mobile/"; + this.iitc_path = Environment.getExternalStorageDirectory().getPath() + + "/IITC_Mobile/"; try { loadIITC_JS(c); - } catch(IOException e) { + } catch (IOException e) { e.printStackTrace(); } } @@ -46,7 +50,8 @@ public class IITC_WebViewClient extends WebViewClient { public String getIITCVersion() { String header = ""; if (js != null) - header = js.substring(js.indexOf("==UserScript=="), js.indexOf("==/UserScript==")); + header = js.substring(js.indexOf("==UserScript=="), + js.indexOf("==/UserScript==")); // remove new line comments header = header.replace("\n//", ""); // get a list of key-value @@ -54,35 +59,46 @@ public class IITC_WebViewClient extends WebViewClient { String iitc_version = "not found"; for (int i = 0; i < attributes.length; i++) { // search for version and use the value - if (attributes[i].equals("@version")) iitc_version = attributes[i+1]; + if (attributes[i].equals("@version")) + iitc_version = attributes[i + 1]; } return iitc_version; } public void loadIITC_JS(Context c) throws java.io.IOException { // You are able to load the script from external source - // if a http address is given, use script from this address. else use the local script - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(c); + // if a http address is given, use script from this address. else use + // the local script + SharedPreferences sharedPref = PreferenceManager + .getDefaultSharedPreferences(c); String iitc_source = sharedPref.getString("pref_iitc_source", "local"); String js = ""; - // if developer mode are enabled, load all iitc script from external storage + // if developer mode are enabled, load all iitc script from external + // storage if (sharedPref.getBoolean("pref_dev_checkbox", false)) { - js = this.fileToString(iitc_path + "dev/total-conversion-build.user.js", 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(); + 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(); + Toast.makeText(context, "Developer mode enabled", + Toast.LENGTH_SHORT).show(); } } 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(); + js = new Scanner(url.openStream(), "UTF-8").useDelimiter("\\A") + .next(); } else { js = this.fileToString("total-conversion-build.user.js", true); } @@ -90,6 +106,15 @@ public class IITC_WebViewClient extends WebViewClient { this.js = js; + PackageManager pm = context.getPackageManager(); + boolean hasMultitouch = pm + .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH); + boolean forcedZoom = sharedPref.getBoolean("pref_user_zoom", false); + if (hasMultitouch && !forcedZoom) { + js = js.replace("window.showZoom = true;", + "window.showZoom = false;"); + } + // need to wrap the mobile iitc.js version in a document ready. IITC // expects to be injected after the DOM has been loaded completely. // Since the mobile client injects IITC by replacing the gen_dashboard @@ -97,17 +122,15 @@ public class IITC_WebViewClient extends WebViewClient { // so it boots correctly. js = "$(document).ready(function(){" + js + "});"; - iitcjs = new WebResourceResponse( - "text/javascript", - "UTF-8", - new ByteArrayInputStream(js.getBytes()) - ); + iitcjs = new WebResourceResponse("text/javascript", "UTF-8", + new ByteArrayInputStream(js.getBytes())); }; // enable https @Override - public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { - handler.proceed() ; + public void onReceivedSslError(WebView view, SslErrorHandler handler, + SslError error) { + handler.proceed(); }; // plugins should be loaded after the main script is injected @@ -116,18 +139,20 @@ public class IITC_WebViewClient extends WebViewClient { super.onPageFinished(view, url); // get the plugin preferences - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences sharedPref = PreferenceManager + .getDefaultSharedPreferences(context); Set plugin_list = sharedPref.getStringSet("pref_plugins", null); - boolean dev_enabled = sharedPref.getBoolean("pref_dev_checkbox", true); + boolean dev_enabled = sharedPref.getBoolean("pref_dev_checkbox", false); // iterate through all enabled plugins and load them if (plugin_list != null) { String[] plugin_array = plugin_list.toArray(new String[0]); - for(int i = 0; i < plugin_list.size(); i++) { + for (int i = 0; i < plugin_list.size(); i++) { Log.d("iitcm", "adding plugin " + plugin_array[i]); if (dev_enabled) - this.loadJS(iitc_path + "dev/plugins/" + plugin_array[i], false, view); + this.loadJS(iitc_path + "dev/plugins/" + plugin_array[i], + false, view); else this.loadJS("plugins/" + plugin_array[i], true, view); } @@ -142,20 +167,21 @@ public class IITC_WebViewClient extends WebViewClient { 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()); + 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..."); - // load plugin from external storage if dev mode are enabled - if (dev_enabled) - this.loadJS(iitc_path + "dev/user-location.user.js", false, view); - else - // load plugin from asset folder - this.loadJS("user-location.user.js", true, view); + // load plugin from external storage if dev mode are enabled + if (dev_enabled) + this.loadJS(iitc_path + "dev/user-location.user.js", false, view); + else + // load plugin from asset folder + this.loadJS("user-location.user.js", true, view); } // read a file into a string @@ -163,7 +189,7 @@ public class IITC_WebViewClient extends WebViewClient { // if asset == true use the asset manager to open file public String fileToString(String file, boolean asset) { Scanner s = null; - String src= ""; + String src = ""; if (!asset) { File js_file = new File(file); try { @@ -185,7 +211,8 @@ public class IITC_WebViewClient extends WebViewClient { } } - if (s != null) src = s.hasNext() ? s.next() : ""; + if (s != null) + src = s.hasNext() ? s.next() : ""; return src; } @@ -197,21 +224,24 @@ public class IITC_WebViewClient extends WebViewClient { String js = fileToString(file, asset); if (js.equals("false")) return false; - else view.loadUrl("javascript:" + js); + else + view.loadUrl("javascript:" + js); return true; } - // Check every external resource if it’s okay to load it and maybe replace it + // Check every external resource if it’s okay to load it and maybe replace + // it // with our own content. This is used to block loading Niantic resources // which aren’t required and to inject IITC early into the site. // via http://stackoverflow.com/a/8274881/1684530 @Override - public WebResourceResponse shouldInterceptRequest (final WebView view, String url) { - if(url.contains("/css/common.css")) { + public WebResourceResponse shouldInterceptRequest(final WebView view, + String url) { + if (url.contains("/css/common.css")) { return new WebResourceResponse("text/css", "UTF-8", style); - } else if(url.contains("gen_dashboard.js")) { + } else if (url.contains("gen_dashboard.js")) { return this.iitcjs; - } else if(url.contains("/css/ap_icons.css") + } else if (url.contains("/css/ap_icons.css") || url.contains("/css/map_icons.css") || url.contains("/css/misc_icons.css") || url.contains("/css/style_full.css") @@ -230,13 +260,18 @@ public class IITC_WebViewClient extends WebViewClient { public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.contains("ingress.com") || url.contains("appengine.google.com")) { // reload iitc if a poslink is clicked inside the app - if (url.contains("intel?ll=") || (url.contains("latE6") && url.contains("lngE6"))) { - Log.d("iitcm", "should be an internal clicked position link...reload script for: " + url); + if (url.contains("intel?ll=") + || (url.contains("latE6") && url.contains("lngE6"))) { + Log.d("iitcm", + "should be an internal clicked position link...reload script for: " + + url); ((IITC_Mobile) context).loadUrl(url); } return false; } else { - Log.d("iitcm", "no ingress intel link, start external app to load url: " + url); + Log.d("iitcm", + "no ingress intel link, start external app to load url: " + + url); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); context.startActivity(intent); return true; diff --git a/plugins/players-resonators.user.js b/plugins/players-resonators.user.js new file mode 100644 index 00000000..28c03791 --- /dev/null +++ b/plugins/players-resonators.user.js @@ -0,0 +1,104 @@ +// ==UserScript== +// @id iitc-plugin-players-resonators@rbino +// @name IITC plugin: Player's Resonators +// @version 0.1.4.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @description [@@BUILDNAME@@-@@BUILDDATE@@] The plugins finds the resonators of a given player. The input is in the sidebar. Useful for revenge. +// @include https://www.ingress.com/intel* +// @include http://www.ingress.com/intel* +// @match https://www.ingress.com/intel* +// @match http://www.ingress.com/intel* +// ==/UserScript== + +/********************************************************************************************************* +* Changelog: +* +* 0.1.4 Added focus link in the toolbox. Some renaming. Removed div to use sidebar style. +* 0.1.3 Effective player name (with wrong capitalization) if it finds some reso +* 0.1.2 Made nickname case insensitive +* 0.1.1 Added mouseover for portal location. Dirty hack to not show mousehover when the alert is fired. +* 0.1.0 First public release +*********************************************************************************************************/ + +function wrapper() { +// ensure plugin framework is there, even if iitc is not yet loaded +if(typeof window.plugin !== 'function') window.plugin = function() {}; + + +// PLUGIN START //////////////////////////////////////////////////////// + +// use own namespace for plugin +window.plugin.playersResonators = function() {}; + +window.plugin.playersResonators.findReso = function(playername) { + var s = ""; + var portalSet = {}; + var effectiveNick = ""; + // Assuming there can be no agents with same nick with different lower/uppercase + var nickToFind = playername.toLowerCase(); + $.each(window.portals, function(ind, portal){ + var r = portal.options.details.resonatorArray.resonators; + $.each(r, function(ind, reso) { + if (!reso) return true; + var nick = getPlayerName(reso.ownerGuid); + if (nick.toLowerCase() === nickToFind){ + if (!effectiveNick) { + effectiveNick = nick; + } + if (!portalSet.hasOwnProperty(portal.options.guid)){ + portalSet[portal.options.guid] = true; + console.log(portalSet); + var latlng = [portal.options.details.locationE6.latE6/1E6, portal.options.details.locationE6.lngE6/1E6].join(); + var guid = portal.options.guid; + var zoomPortal = 'window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false'; + var perma = '/intel?latE6='+portal.options.details.locationE6.latE6+'&lngE6='+portal.options.details.locationE6.lngE6+'&z=17&pguid='+guid; + var a = $('',{ + "class": 'help', + text: portal.options.details.portalV2.descriptiveText.TITLE, + title: portal.options.details.portalV2.descriptiveText.ADDRESS, + href: perma, + onClick: zoomPortal + })[0].outerHTML; + s += a + "\n"; + } + } + }); + }); + if (s) { + // Showing the playername as a "fake" link to avoid the auto-mouseover effect on the first portal + fakeLinkPlayer = '' + effectiveNick + '' + s = fakeLinkPlayer + " has resonators on these portals:\n\n" + s; + } else { + s = playername + " has no resonators in this range\n"; + } + alert(s); +} + +var setup = function() { + var content = ''; + $('#sidebar').append(content); + $('#toolbox').append(' Player\'s Reso'); + $("#playerReso").keypress(function(e) { + if((e.keyCode ? e.keyCode : e.which) !== 13) return; + var data = $(this).val(); + window.plugin.playersResonators.findReso(data); + }); +} + +// PLUGIN END ////////////////////////////////////////////////////////// + +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} +} // wrapper end +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script);