diff --git a/build.py b/build.py
index 42b1e4bf..8d64942b 100755
--- a/build.py
+++ b/build.py
@@ -8,7 +8,14 @@ import base64
import sys
import os
import shutil
+import json
+import shelve
+import hashlib
+try:
+ import urllib2
+except ImportError:
+ import urllib.request as urllib2
# load settings file
from buildsettings import buildSettings
@@ -66,6 +73,33 @@ def loaderRaw(var):
fn = var.group(1)
return readfile(fn)
+def loaderMD(var):
+ fn = var.group(1)
+ # use different MD.dat's for python 2 vs 3 incase user switches versions, as they are not compatible
+ db = shelve.open('build/MDv' + str(sys.version_info.major) + '.dat')
+ if 'files' in db:
+ files = db['files']
+ else:
+ files = {}
+ file = readfile(fn)
+ filemd5 = hashlib.md5(file.encode('utf8')).hexdigest()
+ # check if file has already been parsed by the github api
+ if fn in files and filemd5 in files[fn]:
+ # use the stored copy if nothing has changed to avoid hiting the api more then the 60/hour when not signed in
+ db.close()
+ return files[fn][filemd5]
+ else:
+ url = 'https://api.github.com/markdown'
+ payload = {'text': file, 'mode': 'markdown'}
+ headers = {'Content-Type': 'application/json'}
+ req = urllib2.Request(url, json.dumps(payload).encode('utf8'), headers)
+ md = urllib2.urlopen(req).read().decode('utf8').replace('\n', '').replace('\'', '\\\'')
+ files[fn] = {}
+ files[fn][filemd5] = md
+ db['files'] = files
+ db.close()
+ return md
+
def loaderImage(var):
fn = var.group(1)
return 'data:image/png;base64,{0}'.format(base64.encodestring(open(fn, 'rb').read()).decode('utf8').replace('\n', ''))
@@ -86,6 +120,7 @@ def doReplacements(script,updateUrl,downloadUrl):
script = re.sub('@@INCLUDERAW:([0-9a-zA-Z_./-]+)@@', loaderRaw, script)
script = re.sub('@@INCLUDESTRING:([0-9a-zA-Z_./-]+)@@', loaderString, script)
+ script = re.sub('@@INCLUDEMD:([0-9a-zA-Z_./-]+)@@', loaderMD, script)
script = re.sub('@@INCLUDEIMAGE:([0-9a-zA-Z_./-]+)@@', loaderImage, script)
script = script.replace('@@BUILDDATE@@', buildDate)
@@ -156,6 +191,14 @@ 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:
@@ -169,7 +212,12 @@ if buildMobile:
pass
shutil.copy(os.path.join(outDir,"total-conversion-build.user.js"), "mobile/assets/iitc.js")
- # TODO? also copy plugins - once the mobile app supports plugins, that is
+ # also copy plugins
+ try:
+ os.makedirs("mobile/assets/plugins")
+ except:
+ pass
+ copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins")
# now launch 'ant' to build the mobile project
diff --git a/code/boot.js b/code/boot.js
index 130f9265..caaad95f 100644
--- a/code/boot.js
+++ b/code/boot.js
@@ -118,8 +118,9 @@ window.setupMap = function() {
//MapQuest offer tiles - http://developer.mapquest.com/web/products/open/map
//their usage policy has no limits (except required notification above 4000 tiles/sec - we're perhaps at 50 tiles/sec based on CloudMade stats)
var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ];
+ var mqTileUrlPrefix = window.location.protocol !== 'https:' ? 'http://{s}.mqcdn.com' : 'https://{s}-s.mqcdn.com';
var mqMapOpt = {attribution: osmAttribution+', Tiles Courtesy of MapQuest', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains};
- var mqMap = new L.TileLayer('http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg',mqMapOpt);
+ var mqMap = new L.TileLayer(mqTileUrlPrefix+'/tiles/1.0.0/map/{z}/{x}/{y}.jpg',mqMapOpt);
//MapQuest satellite coverage outside of the US is rather limited - so not really worth having as we have google as an option
//var mqSatOpt = {attribution: 'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains};
//var mqSat = new L.TileLayer('http://{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg',mqSatOpt);
@@ -128,8 +129,8 @@ window.setupMap = function() {
/*0*/ mqMap,
/*1*/ new L.Google('INGRESS'),
/*2*/ new L.Google('ROADMAP'),
- /*3*/ new L.Google('SATELLITE'),
- /*4*/ new L.Google('HYBRID')
+ /*3*/ new L.Google('SATELLITE',{maxZoom:20}),
+ /*4*/ new L.Google('HYBRID',{maxZoom:20})
];
diff --git a/code/chat.js b/code/chat.js
index 919ce854..df42dd2a 100644
--- a/code/chat.js
+++ b/code/chat.js
@@ -410,12 +410,12 @@ window.chat.renderMsg = function(msg, nick, time, team, msgToPlayer, systemNarro
var s = 'style="cursor:pointer; color:'+color+'"';
var title = nick.length >= 8 ? 'title="'+nick+'" class="help"' : '';
var i = ['<', '>'];
- return '
'+t+' | '+i[0]+''+ nick+''+i[1]+' | '+msg+' |
';
+ return ''+t+' | '+i[0]+''+ nick+''+i[1]+' | '+msg+' |
';
}
window.chat.addNickname= function(nick){
var c = document.getElementById("chattext");
- c.value = [c.value, nick, " "].join(" ").trim() + " ";
+ c.value = [c.value.trim(), nick].join(" ").trim() + " ";
c.focus()
}
@@ -589,7 +589,11 @@ window.chat.setup = function() {
window.requests.addRefreshFunction(chat.request);
var cls = PLAYER.team === 'ALIENS' ? 'enl' : 'res';
- $('#chatinput mark').addClass(cls)
+ $('#chatinput mark').addClass(cls);
+
+ $(window).on('click', '.nickname', function(event) {
+ window.chat.nicknameClicked(event, $(this).text());
+ });
}
diff --git a/code/map_data.js b/code/map_data.js
index 8f9a42d4..419534f0 100644
--- a/code/map_data.js
+++ b/code/map_data.js
@@ -12,34 +12,30 @@ window.requestData = function() {
requests.abort();
cleanUp();
- var magic = convertCenterLat(map.getCenter().lat);
- var R = calculateR(magic);
-
var bounds = map.getBounds();
- // convert to point values
- topRight = convertLatLngToPoint(bounds.getNorthEast(), magic, R);
- bottomLeft = convertLatLngToPoint(bounds.getSouthWest() , magic, R);
- // how many quadrants intersect the current view?
- quadsX = Math.abs(bottomLeft.x - topRight.x);
- quadsY = Math.abs(bottomLeft.y - topRight.y);
+
+ var x1 = lngToTile(bounds.getNorthWest().lng, map.getZoom());
+ var x2 = lngToTile(bounds.getNorthEast().lng, map.getZoom());
+ var y1 = latToTile(bounds.getNorthWest().lat, map.getZoom());
+ var y2 = latToTile(bounds.getSouthWest().lat, map.getZoom());
// will group requests by second-last quad-key quadrant
tiles = {};
// walk in x-direction, starts right goes left
- for(var i = 0; i <= quadsX; i++) {
- var x = Math.abs(topRight.x - i);
- var qk = pointToQuadKey(x, topRight.y);
- var bnds = convertPointToLatLng(x, topRight.y, magic, R);
- if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = [];
- tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds));
-
- // walk in y-direction, starts top, goes down
- for(var j = 1; j <= quadsY; j++) {
- var qk = pointToQuadKey(x, topRight.y + j);
- var bnds = convertPointToLatLng(x, topRight.y + j, magic, R);
- if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = [];
- tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds));
+ for (var x = x1; x <= x2; x++) {
+ for (var y = y1; y <= y2; y++) {
+ var tile_id = pointToTileId(map.getZoom(), x, y);
+ var bucket = Math.floor(x / 2) + "" + Math.floor(y / 2);
+ if (!tiles[bucket])
+ tiles[bucket] = [];
+ tiles[bucket].push(generateBoundsParams(
+ tile_id,
+ tileToLat(y + 1, map.getZoom()),
+ tileToLng(x, map.getZoom()),
+ tileToLat(y, map.getZoom()),
+ tileToLng(x + 1, map.getZoom())
+ ));
}
}
@@ -47,7 +43,7 @@ window.requestData = function() {
portalRenderLimit.init();
// finally send ajax requests
$.each(tiles, function(ind, tls) {
- data = { minLevelOfDetail: -1 };
+ data = { zoom: map.getZoom() };
data.boundsParamsList = tls;
window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, window.handleFailedRequest));
});
@@ -78,7 +74,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
// portals can be brought to front, this costs extra time. They need
// to be in the foreground, or they cannot be clicked. See
// https://github.com/Leaflet/Leaflet/issues/185
- var ppp = [];
+ var ppp = {};
var p2f = {};
$.each(m, function(qk, val) {
$.each(val.deletedGameEntityGuids || [], function(ind, guid) {
@@ -105,9 +101,17 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
&& urlPortal !== ent[0]
) return;
+ if('imageByUrl' in ent[2] && 'imageUrl' in ent[2].imageByUrl) {
+ if(window.location.protocol === 'https:') {
+ ent[2].imageByUrl.imageUrl = ent[2].imageByUrl.imageUrl.indexOf('www.panoramio.com') !== -1
+ ? ent[2].imageByUrl.imageUrl.replace(/^http:\/\/www/, 'https://ssl').replace('small', 'medium')
+ : ent[2].imageByUrl.imageUrl.replace(/^http:\/\//, '//');
+ }
+ } else {
+ ent[2].imageByUrl = {'imageUrl': DEFAULT_PORTAL_IMG};
+ }
-
- ppp.push(ent); // delay portal render
+ ppp[ent[0]] = ent; // delay portal render
} else if(ent[2].edge !== undefined) {
renderLink(ent);
} else if(ent[2].capturedRegion !== undefined) {
@@ -124,6 +128,25 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
});
$.each(ppp, function(ind, portal) {
+ if ('portalV2' in portal[2] && 'linkedEdges' in portal[2].portalV2) {
+ $.each(portal[2].portalV2.linkedEdges, function (ind, edge) {
+ if (!ppp[edge.otherPortalGuid])
+ return;
+ renderLink([
+ edge.edgeGuid,
+ portal[1],
+ {
+ "controllingTeam": portal[2].controllingTeam,
+ "edge": {
+ "destinationPortalGuid": edge.isOrigin ? ppp[edge.otherPortalGuid][0] : portal[0],
+ "destinationPortalLocation": edge.isOrigin ? ppp[edge.otherPortalGuid][2].locationE6 : portal[2].locationE6,
+ "originPortalGuid": !edge.isOrigin ? ppp[edge.otherPortalGuid][0] : portal[0],
+ "originPortalLocation": !edge.isOrigin ? ppp[edge.otherPortalGuid][2].locationE6 : portal[2].locationE6
+ }
+ }
+ ]);
+ });
+ }
if(portal[2].portalV2['linkedFields'] === undefined) {
portal[2].portalV2['linkedFields'] = [];
}
diff --git a/code/map_data_calc_tools.js b/code/map_data_calc_tools.js
index 2f383197..98535759 100644
--- a/code/map_data_calc_tools.js
+++ b/code/map_data_calc_tools.js
@@ -1,79 +1,45 @@
-
-
// MAP DATA REQUEST CALCULATORS //////////////////////////////////////
// Ingress Intel splits up requests for map data (portals, links,
// fields) into tiles. To get data for the current viewport (i.e. what
// is currently visible) it first calculates which tiles intersect.
// For all those tiles, it then calculates the lat/lng bounds of that
// tile and a quadkey. Both the bounds and the quadkey are “somewhat”
-// required to get complete data. No idea how the projection between
-// lat/lng and tiles works.
-// What follows now are functions that allow conversion between tiles
-// and lat/lng as well as calculating the quad key. The variable names
-// may be misleading.
-// The minified source for this code was in gen_dashboard.js after the
-// “// input 89” line (alternatively: the class was called “Xe”).
+// required to get complete data.
+//
+// Convertion functions courtesy of
+// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
-window.convertCenterLat = function(centerLat) {
- return Math.round(256 * 0.9999 * Math.abs(1 / Math.cos(centerLat * DEG2RAD)));
+window.lngToTile = function(lng, zoom) {
+ return Math.floor((lng + 180) / 360 * Math.pow(2, zoom));
}
-window.calculateR = function(convCenterLat) {
- return 1 << window.map.getZoom() - (convCenterLat / 256 - 1);
+window.latToTile = function(lat, zoom) {
+ return Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) +
+ 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom));
}
-window.convertLatLngToPoint = function(latlng, magic, R) {
- var x = (magic/2 + latlng.lng * magic / 360)*R;
- var l = Math.sin(latlng.lat * DEG2RAD);
- var y = (magic/2 + 0.5*Math.log((1+l)/(1-l)) * -(magic / (2*Math.PI)))*R;
- return {x: Math.floor(x/magic), y: Math.floor(y/magic)};
+window.tileToLng = function(x, zoom) {
+ return x / Math.pow(2, zoom) * 360 - 180;
}
-window.convertPointToLatLng = function(x, y, magic, R) {
- var e = {};
- e.sw = {
- // orig function put together from all over the place
- // lat: (2 * Math.atan(Math.exp((((y + 1) * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180),
- // shortened version by your favorite algebra program.
- lat: (360*Math.atan(Math.exp(Math.PI - 2*Math.PI*(y+1)/R)))/Math.PI - 90,
- lng: 360*x/R-180
- };
- e.ne = {
- //lat: (2 * Math.atan(Math.exp(((y * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180),
- lat: (360*Math.atan(Math.exp(Math.PI - 2*Math.PI*y/R)))/Math.PI - 90,
- lng: 360*(x+1)/R-180
- };
- return e;
+window.tileToLat = function(y, zoom) {
+ var n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom);
+ return 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
}
-// calculates the quad key for a given point. The point is not(!) in
-// lat/lng format.
-window.pointToQuadKey = function(x, y) {
- var quadkey = [];
- for(var c = window.map.getZoom(); c > 0; c--) {
- // +-------+ quadrants are probably ordered like this
- // | 0 | 1 |
- // |---|---|
- // | 2 | 3 |
- // |---|---|
- var quadrant = 0;
- var e = 1 << c - 1;
- (x & e) != 0 && quadrant++; // push right
- (y & e) != 0 && (quadrant++, quadrant++); // push down
- quadkey.push(quadrant);
- }
- return quadkey.join("");
+window.pointToTileId = function(zoom, x, y) {
+ return zoom + "_" + x + "_" + y;
}
-// given quadkey and bounds, returns the format as required by the
+// given tile id and bounds, returns the format as required by the
// Ingress API to request map data.
-window.generateBoundsParams = function(quadkey, bounds) {
+window.generateBoundsParams = function(tile_id, minLat, minLng, maxLat, maxLng) {
return {
- id: quadkey,
- qk: quadkey,
- minLatE6: Math.round(bounds.sw.lat * 1E6),
- minLngE6: Math.round(bounds.sw.lng * 1E6),
- maxLatE6: Math.round(bounds.ne.lat * 1E6),
- maxLngE6: Math.round(bounds.ne.lng * 1E6)
+ id: tile_id,
+ qk: tile_id,
+ minLatE6: Math.round(minLat * 1E6),
+ minLngE6: Math.round(minLng * 1E6),
+ maxLatE6: Math.round(maxLat * 1E6),
+ maxLngE6: Math.round(maxLng * 1E6)
};
}
diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js
index 8937da8f..636230ed 100644
--- a/code/portal_detail_display.js
+++ b/code/portal_detail_display.js
@@ -44,10 +44,7 @@ window.renderPortalDetails = function(guid) {
var resoDetails = '' + getResonatorDetails(d) + '
';
setPortalIndicators(d);
- var img = d.imageByUrl && d.imageByUrl.imageUrl
- ? d.imageByUrl.imageUrl
- : DEFAULT_PORTAL_IMG;
-
+ var img = d.imageByUrl.imageUrl;
var lat = d.locationE6.latE6;
var lng = d.locationE6.lngE6;
var perma = '/intel?latE6='+lat+'&lngE6='+lng+'&z=17&pguid='+guid;
diff --git a/code/utils_misc.js b/code/utils_misc.js
index 84562c92..267a1c06 100644
--- a/code/utils_misc.js
+++ b/code/utils_misc.js
@@ -1,7 +1,8 @@
// UTILS + MISC ///////////////////////////////////////////////////////
window.aboutIITC = function(){
- var v = '@@BUILDNAME@@-@@BUILDDATE@@'
+ var v = '@@BUILDNAME@@-@@BUILDDATE@@';
+ var attrib = '@@INCLUDEMD:ATTRIBUTION.md@@';
var a = ''
+ ' About IITC
'
+ ' Ingress Intel Total Conversion
'
@@ -20,8 +21,11 @@ window.aboutIITC = function(){
+ ' MapQuest OSM tiles Courtesy of MapQuest
'
+ ' '
+ '
'
- + ' Version: ' + v + '
';
- alert(a);
+ + ' Version: ' + v + '
'
+ + '
'
+ + ' ' + attrib + '
';
+ alert(a, true, function() {$('.ui-dialog').removeClass('ui-dialog-aboutIITC');});
+ $('.ui-dialog').addClass('ui-dialog-aboutIITC');
}
@@ -197,8 +201,8 @@ window.renderLimitReached = function(ratio) {
window.getMinPortalLevel = function() {
var z = map.getZoom();
- if(z >= 16) return 0;
- var conv = ['impossible', 8,7,7,6,6,5,5,4,4,3,3,2,2,1,1];
+ if(z >= 17) return 0;
+ var conv = ['impossible', 8,8,8,7,7,6,6,5,4,4,3,3,2,2,1,1];
var minLevelByRenderLimit = portalRenderLimit.getMinLevel();
var result = minLevelByRenderLimit > conv[z]
? minLevelByRenderLimit
diff --git a/main.js b/main.js
index 9e57ee01..3bebd816 100644
--- a/main.js
+++ b/main.js
@@ -1,7 +1,7 @@
// ==UserScript==
// @id ingress-intel-total-conversion@jonatkins
// @name IITC: Ingress intel map total conversion
-// @version 0.10.5.@@DATETIMEVERSION@@
+// @version 0.11.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@@ -87,7 +87,7 @@ document.getElementsByTagName('body')[0].innerHTML = ''
+ ' loading global control stats
'
+ ' '
+ '
'
- + '

'
+ + '

'
+ '
'
+ ' '
+ ' '
diff --git a/mobile/.gitignore b/mobile/.gitignore
index a56e372f..42222e62 100644
--- a/mobile/.gitignore
+++ b/mobile/.gitignore
@@ -7,3 +7,4 @@ libs/
proguard-project.txt
local.properties
assets/iitc.js
+assets/plugins/
diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml
index d3fa4d8f..844d7462 100644
--- a/mobile/AndroidManifest.xml
+++ b/mobile/AndroidManifest.xml
@@ -1,8 +1,8 @@
+ android:versionCode="11"
+ android:versionName="0.3" >
UI
+ Plugins
+ Available plugins
Force desktop mode
Nice for tablets, looks awful on smartphones
Developer options
diff --git a/mobile/res/xml/preferences.xml b/mobile/res/xml/preferences.xml
index fd50c037..2d72b3e1 100644
--- a/mobile/res/xml/preferences.xml
+++ b/mobile/res/xml/preferences.xml
@@ -17,6 +17,10 @@
android:title="@string/pref_force_desktop"
android:summary="@string/pref_force_desktop_sum"
android:defaultValue="false" />
+
asset_list = new ArrayList();
+ 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]);
+ }
+ }
+
+ 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]));
+ settings.setArguments(bundle);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java b/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java
index 34e3c0c0..5a68f307 100644
--- a/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java
@@ -6,6 +6,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
+import android.preference.MultiSelectListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
@@ -21,7 +22,12 @@ public class IITC_SettingsFragment extends PreferenceFragment {
iitc_version = getArguments().getString("iitc_version");
addPreferencesFromResource(R.xml.preferences);
-
+
+ //plugins
+ MultiSelectListPreference pref_plugins = (MultiSelectListPreference) findPreference("pref_plugins");
+ pref_plugins.setEntries(getArguments().getStringArray("ASSETS"));
+ pref_plugins.setEntryValues(getArguments().getStringArray("ASSETS_VAL"));
+
// set build version
ListPreference pref_build_version = (ListPreference) findPreference("pref_build_version");
PackageManager pm = getActivity().getPackageManager();
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java
index d92d189d..d2a62897 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.res.AssetManager;
import android.net.Uri;
import android.net.http.SslError;
import android.preference.PreferenceManager;
@@ -17,6 +18,7 @@ import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Scanner;
+import java.util.Set;
public class IITC_WebViewClient extends WebViewClient {
private static final ByteArrayInputStream style = new ByteArrayInputStream(
@@ -44,7 +46,7 @@ public class IITC_WebViewClient extends WebViewClient {
String[] attributes = header.split(" +");
String iitc_version = "not found";
for (int i = 0; i < attributes.length; i++) {
- // search vor version and use the value
+ // search for version and use the value
if (attributes[i].equals("@version")) iitc_version = attributes[i+1];
}
return iitc_version;
@@ -91,6 +93,39 @@ public class IITC_WebViewClient extends WebViewClient {
handler.proceed() ;
};
+ // plugins should be loaded after the main script is injected
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ super.onPageFinished(view, url);
+
+ // get the plugin preferences
+ SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
+ Set plugin_list = sharedPref.getStringSet("pref_plugins", null);
+
+ // 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 {
+ 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);
+ }
+ }
+ }
+ }
+
// 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.
@@ -119,6 +154,11 @@ public class IITC_WebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("ingress.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);
+ ((IITC_Mobile) context).loadUrl(url);
+ }
return false;
} else {
Log.d("iitcm", "no ingress intel link, start external app to load url: " + url);
diff --git a/plugins/ap-list.user.js b/plugins/ap-list.user.js
index c8a4d575..9bf1c09a 100644
--- a/plugins/ap-list.user.js
+++ b/plugins/ap-list.user.js
@@ -1,11 +1,11 @@
// ==UserScript==
// @id iitc-plugin-ap-list@xelio
// @name IITC plugin: AP List
-// @version 0.5.1.@@DATETIMEVERSION@@
+// @version 0.5.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
-// @description [@@BUILDNAME@@-@@BUILDDATE@@] List top 10 portals by AP of either faction. Other functions and controls please refer to the Userguide.
+// @description [@@BUILDNAME@@-@@BUILDDATE@@] List portals by AP of either faction or by effective level. Other functions and controls please refer to the Userguide.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
diff --git a/plugins/ipas-link.user.js b/plugins/ipas-link.user.js
index 50f7c994..ac158c10 100644
--- a/plugins/ipas-link.user.js
+++ b/plugins/ipas-link.user.js
@@ -1,7 +1,7 @@
// ==UserScript==
// @id iitc-plugin-ipas-link@graphracer
// @name IITC Plugin: simulate an attack on portal
-// @version 0.1.1.@@DATETIMEVERSION@@
+// @version 0.2.0.@@DATETIMEVERSION@@
// @namespace https://github.com/xosofox/IPAS
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@@ -30,16 +30,34 @@ window.plugin.ipasLink.addLink = function(d) {
$('.linkdetails').append('');
}
-window.plugin.ipasLink.getHash = function(d) {
- var hashParts=[];
- $.each(d.resonatorArray.resonators, function(ind, reso) {
- if (reso) {
- hashParts.push(reso.level + "," + reso.distanceToPortal + "," + reso.energyTotal);
- } else {
- hashParts.push(1 + "," + 35 + "," + 0); // Dummy values, the only important one is energy=0
- }
- });
- return hashParts.join(";")+"|" + "0,0,0,0"; //shields not implemented yet
+window.plugin.ipasLink.getHash = function (d) {
+ var hashParts = [];
+ $.each(d.resonatorArray.resonators, function (ind, reso) {
+ if (reso) {
+ hashParts.push(reso.level + "," + reso.distanceToPortal + "," + reso.energyTotal);
+ } else {
+ hashParts.push("1,20,0");
+ }
+ });
+ var resos = hashParts.join(";");
+
+ hashParts = [];
+ $.each(d.portalV2.linkedModArray, function (ind, mod) {
+ //shields only, so far...
+ var s = "0";
+ if (mod) {
+ if (mod.type === "RES_SHIELD") {
+ s = mod.rarity.charAt(0).toLowerCase();
+ }
+ }
+ hashParts.push(s);
+ });
+ var shields = hashParts.join(",");
+ return resos + "|" + shields;
+}
+
+var setup = function () {
+ window.plugin.ipasLink.setupCallback();
}
var setup = function() {
diff --git a/plugins/player-tracker.user.js b/plugins/player-tracker.user.js
index 864a006a..7f20df6c 100644
--- a/plugins/player-tracker.user.js
+++ b/plugins/player-tracker.user.js
@@ -266,12 +266,13 @@ window.plugin.playerTracker.drawData = function() {
if(window.plugin.guessPlayerLevels !== undefined &&
window.plugin.guessPlayerLevels.fetchLevelByPlayer !== undefined) {
var playerLevel = window.plugin.guessPlayerLevels.fetchLevelByPlayer(pguid);
- if (playerLevel === undefined) playerLevel = 1; //if player level unknown, assume level 1
if(playerLevel !== undefined) {
title += 'Level '
+ playerLevel
+ (playerLevel < (window.MAX_XM_PER_LEVEL.length - 1) ? ' (guessed)' : '')
+ '';
+ } else {
+ title += 'Level unknown'
}
}
diff --git a/plugins/portal-highlighter-level-color.user.js b/plugins/portal-highlighter-level-color.user.js
new file mode 100644
index 00000000..ac6344ff
--- /dev/null
+++ b/plugins/portal-highlighter-level-color.user.js
@@ -0,0 +1,51 @@
+// ==UserScript==
+// @id iitc-plugin-highlight-portals-level-color@vita10gy
+// @name IITC plugin: highlight portals by level color
+// @version 0.1.0.@@DATETIMEVERSION@@
+// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
+// @updateURL @@UPDATEURL@@
+// @downloadURL @@DOWNLOADURL@@
+// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals level color.
+// @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==
+
+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.portalHighligherPortalsLevelColor = function() {};
+
+window.plugin.portalHighligherPortalsLevelColor.colorLevel = function(data) {
+ var d = data.portal.options.details;
+ var portal_level = Math.floor(getPortalLevel(d));
+ var opacity = .6;
+ data.portal.setStyle({fillColor: COLORS_LVL[portal_level], fillOpacity: opacity});
+ window.COLOR_SELECTED_PORTAL = '#f0f';
+}
+
+var setup = function() {
+ window.addPortalHighlighter('Level Color', window.plugin.portalHighligherPortalsLevelColor.colorLevel);
+}
+
+// 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);
diff --git a/plugins/portal-highlighter-portal-ap-energy-relative.user.js b/plugins/portal-highlighter-portal-ap-energy-relative.user.js
new file mode 100644
index 00000000..677c2ab5
--- /dev/null
+++ b/plugins/portal-highlighter-portal-ap-energy-relative.user.js
@@ -0,0 +1,118 @@
+// ==UserScript==
+// @id iitc-plugin-highlight-portals-by-ap-by-energy-relative@vita10gy
+// @name IITC plugin: highlight portals by ap/energy (relative)
+// @version 0.1.1.@@DATETIMEVERSION@@
+// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
+// @updateURL @@UPDATEURL@@
+// @downloadURL @@DOWNLOADURL@@
+// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote AP/Energy value relative to what's currently on the screen. Brighter is better. Orange means your standard 8 down 8 up swap.
+// @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==
+
+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.portalHighligherPortalAPPerEnergyRelative = function() {};
+
+window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = null;
+window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = null;
+//This is the AP for a run of the mill takedown/putback
+window.plugin.portalHighligherPortalAPPerEnergyRelative.baseSwapAP = 2350;
+
+
+window.plugin.portalHighligherPortalAPPerEnergyRelative.highlight = function(data) {
+ var d = data.portal.options.details;
+ var color = 'red';
+
+ if(window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP == null ||
+ window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP == null) {
+ window.plugin.portalHighligherPortalAPPerEnergyRelative.calculateAPLevels();
+ }
+ var minApE = window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP;
+ var maxApE = window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP;
+
+ if(PLAYER.team !== d.controllingTeam.team) {
+ var ap = getAttackApGain(d);
+ var energy = getCurrentPortalEnergy(d);
+ if(energy < 1) {
+ energy = 1;
+ }
+ portal_ap = ap.enemyAp;
+
+ var opacity = 1;
+ if(minApE !== maxApE) {
+ opacity = ((ap.enemyAp / energy) - minApE) / (maxApE - minApE);
+ }
+
+ if(opacity < 0) {
+ opacity = 0;
+ }
+ if(opacity > 1) {
+ opacity = 1;
+ }
+ data.portal.setStyle({fillColor: color, fillOpacity: opacity});
+ window.COLOR_SELECTED_PORTAL = '#f0f';
+ }
+}
+
+window.plugin.portalHighligherPortalAPPerEnergyRelative.resetAPLevels = function() {
+ window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = null;
+ window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = null;
+}
+
+window.plugin.portalHighligherPortalAPPerEnergyRelative.calculateAPLevels = function() {
+ var displayBounds = map.getBounds();
+ $.each(window.portals, function(qk, portal) {
+ if(displayBounds.contains(portal.getLatLng())) {
+ if(PLAYER.team !== portal.options.details.controllingTeam.team) {
+ var ap = getAttackApGain(portal.options.details);
+ var energy = getCurrentPortalEnergy(portal.options.details);
+ if(energy < 1) {
+ energy = 1;
+ }
+ var portal_ap = ap.enemyAp / energy;
+ if(window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP === null ||
+ portal_ap < window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP) {
+ window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = portal_ap;
+ }
+ if(window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP === null ||
+ portal_ap > window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP) {
+ window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = portal_ap;
+ }
+
+ }
+ }
+ });
+}
+
+
+
+var setup = function() {
+ window.addPortalHighlighter('AP/Energy (Relative)', window.plugin.portalHighligherPortalAPPerEnergyRelative.highlight);
+ window.addHook('requestFinished', window.plugin.portalHighligherPortalAPPerEnergyRelative.resetAPLevels);
+
+}
+
+// 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);
diff --git a/plugins/portal-highlighter-portal-ap-relative.user.js b/plugins/portal-highlighter-portal-ap-relative.user.js
index 08059865..a96941bb 100644
--- a/plugins/portal-highlighter-portal-ap-relative.user.js
+++ b/plugins/portal-highlighter-portal-ap-relative.user.js
@@ -90,10 +90,8 @@ window.plugin.portalHighligherPortalAPRelative.calculateAPLevels = function() {
});
}
-
-
var setup = function() {
- window.addPortalHighlighter('Portal AP (Relative)', window.plugin.portalHighligherPortalAPRelative.highlight);
+ window.addPortalHighlighter('AP (Relative)', window.plugin.portalHighligherPortalAPRelative.highlight);
window.addHook('requestFinished', window.plugin.portalHighligherPortalAPRelative.resetAPLevels);
}
diff --git a/plugins/portal-highlighter-portal-ap.user.js b/plugins/portal-highlighter-portal-ap.user.js
index 3dc17f6c..30ced897 100644
--- a/plugins/portal-highlighter-portal-ap.user.js
+++ b/plugins/portal-highlighter-portal-ap.user.js
@@ -54,7 +54,7 @@ window.plugin.portalHighligherPortalAP.highlight = function(data) {
}
var setup = function() {
- window.addPortalHighlighter('Portal AP', window.plugin.portalHighligherPortalAP.highlight);
+ window.addPortalHighlighter('AP (Static)', window.plugin.portalHighligherPortalAP.highlight);
}
// PLUGIN END //////////////////////////////////////////////////////////
diff --git a/plugins/scale-bar.user.js b/plugins/scale-bar.user.js
index 5e784c12..23329456 100644
--- a/plugins/scale-bar.user.js
+++ b/plugins/scale-bar.user.js
@@ -28,7 +28,7 @@ window.plugin.scaleBar.setup = function() {
// Before you ask: yes, I explicitely turned off imperial units. Imperial units
// are worse than Internet Explorer 6 whirring fans combined. Upgrade to the metric
// system already.
- window.map.addControl(new L.Control.Scale({position: 'topleft', imperial: false}));
+ window.map.addControl(new L.Control.Scale({position: 'topleft', imperial: false, maxWidth: 200}));
};
var setup = window.plugin.scaleBar.setup;
diff --git a/plugins/show-linked-portals.user.js b/plugins/show-linked-portals.user.js
index a42003d0..e380557c 100644
--- a/plugins/show-linked-portals.user.js
+++ b/plugins/show-linked-portals.user.js
@@ -71,9 +71,18 @@ window.plugin.showLinkedPortal.getPortalByGuid = function (guid) {
var portalDetails = window.portals[guid].options.details;
portalInfoString = '';
var portalNameAdressAlt = "'" + portalDetails.portalV2.descriptiveText.TITLE + "' (" + portalDetails.portalV2.descriptiveText.ADDRESS + ")";
- var portalNameAdressTitle = "'" + portalDetails.portalV2.descriptiveText.TITLE + "'
(" + portalDetails.portalV2.descriptiveText.ADDRESS + ")";
+ var portalNameAdressTitle = $('').append('\'')
+ .append($('').text(portalDetails.portalV2.descriptiveText.TITLE))
+ .append('\'')
+ .append($('
'))
+ .append($('').text('(' + portalDetails.portalV2.descriptiveText.ADDRESS + ')'))
+ .html();
var imageUrl = (portalDetails.imageByUrl ? portalDetails.imageByUrl.imageUrl : window.DEFAULT_PORTAL_IMG);
- portalInfoString = '
';
+ portalInfoString = $('').html($('
').attr('src', imageUrl)
+ .attr('class', 'minImg')
+ .attr('alt', portalNameAdressAlt)
+ .attr('title', portalNameAdressTitle))
+ .html();
}
return portalInfoString;
};
diff --git a/style.css b/style.css
index e1827e13..ad563fe2 100644
--- a/style.css
+++ b/style.css
@@ -68,6 +68,10 @@ body {
color: #fff;
}
+.nickname {
+ cursor: pointer !important;
+}
+
a {
color: #ffce00;
cursor: pointer;
@@ -434,6 +438,7 @@ input {
#geosearchwrapper img{
vertical-align: bottom;
margin-bottom: 2px;
+ cursor: pointer;
}
::-webkit-input-placeholder {
font-style: italic;
@@ -691,9 +696,8 @@ h3 {
}
#largepreview img {
box-shadow: 0 0 40px #000;
-}
-#largepreview img {
border: 2px solid #f8ff5e;
+ background-color: rgba(8, 48, 78, 0.9); /* as some images - eg ZipCar - have transparency */
}
/* tooltips, dialogs */
@@ -762,6 +766,11 @@ h3 {
text-decoration: underline;
}
+.ui-dialog-aboutIITC {
+ max-width: 600px !important;
+ width: 600px !important;
+}
+
td {
padding: 0;
vertical-align: top;