merged
This commit is contained in:
commit
dea1266568
@ -10,5 +10,8 @@ This project is licensed under the permissive [ISC license](http://www.isc.org/d
|
||||
- [taphold.js by Rich Adams; unknown](https://github.com/richadams/jquery-taphold)
|
||||
- [L.Control.Pan.js by Kartena AB; same as Leaflet](https://github.com/kartena/Leaflet.Pancontrol)
|
||||
- [L.Control.Zoomslider.js by Kartena AB; same as Leaflet](https://github.com/kartena/Leaflet.zoomslider)
|
||||
- [KML.js by shramov; same as Leaflet](https://github.com/shramov/leaflet-plugins)
|
||||
- [leaflet.filelayer.js by shramov; same as Leaflet](https://github.com/shramov/leaflet-plugins)
|
||||
- [togeojson.js by shramov; same as Leaflet](https://github.com/shramov/leaflet-plugins)
|
||||
- StackOverflow-CopyPasta is attributed in the source; [CC-Wiki](https://creativecommons.org/licenses/by-sa/3.0/)
|
||||
- all Ingress/Niantic related stuff obviously remains non-free and is still copyrighted by Niantic/Google
|
||||
|
@ -8,7 +8,9 @@ So far, these people have contributed:
|
||||
[ccjon](https://github.com/ccjon),
|
||||
[cmrn](https://github.com/cmrn),
|
||||
[epf](https://github.com/epf),
|
||||
[fkloft](https://github.com/fkloft),
|
||||
[Fragger](https://github.com/Fragger),
|
||||
[hastarin](https://github.com/hastarin),
|
||||
[integ3r](https://github.com/integ3r),
|
||||
[j16sdiz](https://github.com/j16sdiz),
|
||||
[JasonMillward](https://github.com/JasonMillward),
|
||||
|
45
build.py
45
build.py
@ -60,29 +60,38 @@ resourceUrlBase = settings.get('resourceUrlBase')
|
||||
distUrlBase = settings.get('distUrlBase')
|
||||
buildMobile = settings.get('buildMobile')
|
||||
antOptions = settings.get('antOptions','')
|
||||
antBuildFile = settings.get('antBuildFile', 'mobile/build.xml');
|
||||
|
||||
|
||||
# plugin wrapper code snippets. handled as macros, to ensure that
|
||||
# 1. indentation caused by the "function wrapper()" doesn't apply to the plugin code body
|
||||
# 2. the wrapper is formatted correctly for removal by the IITC Mobile android app
|
||||
pluginWrapperStart = """
|
||||
function wrapper() {
|
||||
function wrapper(plugin_info) {
|
||||
// ensure plugin framework is there, even if iitc is not yet loaded
|
||||
if(typeof window.plugin !== 'function') window.plugin = function() {};
|
||||
|
||||
//PLUGIN AUTHORS: writing a plugin outside of the IITC build environment? if so, delete these lines!!
|
||||
//(leaving them in place might break the 'About IITC' page or break update checks)
|
||||
plugin_info.buildName = '@@BUILDNAME@@';
|
||||
plugin_info.dateTimeVersion = '@@DATETIMEVERSION@@';
|
||||
plugin_info.pluginId = '@@PLUGINNAME@@';
|
||||
//END PLUGIN AUTHORS NOTE
|
||||
|
||||
"""
|
||||
|
||||
pluginWrapperEnd = """
|
||||
if(window.iitcLoaded && typeof setup === 'function') {
|
||||
setup();
|
||||
} else {
|
||||
if(window.bootPlugins)
|
||||
window.bootPlugins.push(setup);
|
||||
else
|
||||
window.bootPlugins = [setup];
|
||||
}
|
||||
setup.info = plugin_info; //add the script info data to the function as a property
|
||||
if(!window.bootPlugins) window.bootPlugins = [];
|
||||
window.bootPlugins.push(setup);
|
||||
// if IITC has already booted, immediately run the 'setup' function
|
||||
if(window.iitcLoaded && typeof setup === 'function') setup();
|
||||
} // wrapper end
|
||||
// inject code into site context
|
||||
var script = document.createElement('script');
|
||||
script.appendChild(document.createTextNode('('+ wrapper +')();'));
|
||||
var info = {};
|
||||
if (typeof GM_info !== 'undefined' && GM_info && GM_info.script) info.script = { version: GM_info.script.version, name: GM_info.script.name, description: GM_info.script.description };
|
||||
script.appendChild(document.createTextNode('('+ wrapper +')('+JSON.stringify(info)+');'));
|
||||
(document.body || document.head || document.documentElement).appendChild(script);
|
||||
|
||||
"""
|
||||
@ -141,10 +150,13 @@ def extractUserScriptMeta(var):
|
||||
|
||||
|
||||
|
||||
def doReplacements(script,updateUrl,downloadUrl):
|
||||
def doReplacements(script,updateUrl,downloadUrl,pluginName=None):
|
||||
|
||||
script = re.sub('@@INJECTCODE@@',loadCode,script)
|
||||
|
||||
script = script.replace('@@PLUGINSTART@@', pluginWrapperStart)
|
||||
script = script.replace('@@PLUGINEND@@', pluginWrapperEnd)
|
||||
|
||||
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)
|
||||
@ -164,8 +176,8 @@ def doReplacements(script,updateUrl,downloadUrl):
|
||||
script = script.replace('@@UPDATEURL@@', updateUrl)
|
||||
script = script.replace('@@DOWNLOADURL@@', downloadUrl)
|
||||
|
||||
script = script.replace('@@PLUGINSTART@@', pluginWrapperStart)
|
||||
script = script.replace('@@PLUGINEND@@', pluginWrapperEnd)
|
||||
if (pluginName):
|
||||
script = script.replace('@@PLUGINNAME@@', pluginName);
|
||||
|
||||
return script
|
||||
|
||||
@ -221,7 +233,8 @@ for fn in glob.glob("plugins/*.user.js"):
|
||||
|
||||
downloadUrl = distUrlBase and distUrlBase + '/' + fn.replace("\\","/") or 'none'
|
||||
updateUrl = distUrlBase and downloadUrl.replace('.user.js', '.meta.js') or 'none'
|
||||
script = doReplacements(script, downloadUrl=downloadUrl, updateUrl=updateUrl)
|
||||
pluginName = os.path.splitext(os.path.splitext(os.path.basename(fn))[0])[0]
|
||||
script = doReplacements(script, downloadUrl=downloadUrl, updateUrl=updateUrl, pluginName=pluginName)
|
||||
|
||||
metafn = fn.replace('.user.js', '.meta.js')
|
||||
saveScriptAndMeta(script, os.path.join(outDir,fn), os.path.join(outDir,metafn))
|
||||
@ -236,7 +249,7 @@ if buildMobile:
|
||||
script = readfile("mobile/plugins/" + fn)
|
||||
downloadUrl = distUrlBase and distUrlBase + '/' + fn.replace("\\","/") or 'none'
|
||||
updateUrl = distUrlBase and downloadUrl.replace('.user.js', '.meta.js') or 'none'
|
||||
script = doReplacements(script, downloadUrl=downloadUrl, updateUrl=updateUrl)
|
||||
script = doReplacements(script, downloadUrl=downloadUrl, updateUrl=updateUrl, pluginName='user-location')
|
||||
|
||||
metafn = fn.replace('.user.js', '.meta.js')
|
||||
saveScriptAndMeta(script, os.path.join(outDir,fn), os.path.join(outDir,metafn))
|
||||
@ -263,7 +276,7 @@ if buildMobile:
|
||||
|
||||
if buildMobile != 'copyonly':
|
||||
# now launch 'ant' to build the mobile project
|
||||
retcode = os.system("ant %s -buildfile mobile/build.xml %s" % (antOptions, buildMobile))
|
||||
retcode = os.system("ant %s -buildfile %s %s" % (antOptions, antBuildFile, buildMobile))
|
||||
|
||||
if retcode != 0:
|
||||
print ("Error: mobile app failed to build. ant returned %d" % retcode)
|
||||
|
14
code/chat.js
14
code/chat.js
@ -540,7 +540,6 @@ window.chat.show = function(name) {
|
||||
? $('#updatestatus').hide()
|
||||
: $('#updatestatus').show();
|
||||
$('#chat, #chatinput').show();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
|
||||
var t = $('<a>'+name+'</a>');
|
||||
window.chat.chooseAnchor(t);
|
||||
@ -681,7 +680,18 @@ window.chat.postMsg = function() {
|
||||
var msg = $.trim($('#chatinput input').val());
|
||||
if(!msg || msg === '') return;
|
||||
|
||||
if(c === 'debug') return new Function (msg)();
|
||||
if(c === 'debug') {
|
||||
var result;
|
||||
try {
|
||||
result = eval(msg);
|
||||
} catch(e) {
|
||||
if(e.stack) console.error(e.stack);
|
||||
throw e; // to trigger native error message
|
||||
}
|
||||
if(result !== undefined)
|
||||
console.log(result.toString());
|
||||
return result;
|
||||
}
|
||||
|
||||
var publik = c === 'public';
|
||||
var latlng = map.getCenter();
|
||||
|
@ -23,10 +23,6 @@ window.debug.console = function() {
|
||||
}
|
||||
|
||||
window.debug.console.show = function() {
|
||||
if (window.isSmartphone()) {
|
||||
$('#scrollwrapper, #updatestatus').hide();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
}
|
||||
$('#chat, #chatinput').show();
|
||||
window.debug.console.create();
|
||||
$('#chatinput mark').css('cssText', 'color: #bbb !important').text('debug:');
|
||||
@ -88,10 +84,20 @@ window.debug.console.error = function(text) {
|
||||
|
||||
window.debug.console.overwriteNative = function() {
|
||||
window.debug.console.create();
|
||||
window.console = function() {}
|
||||
window.console.log = window.debug.console.log;
|
||||
window.console.warn = window.debug.console.warn;
|
||||
window.console.error = window.debug.console.error;
|
||||
|
||||
var nativeConsole = window.console;
|
||||
window.console = {};
|
||||
|
||||
function overwrite(which) {
|
||||
window.console[which] = function() {
|
||||
nativeConsole[which].apply(nativeConsole, arguments);
|
||||
window.debug.console[which].apply(window.debug.console, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
overwrite("log");
|
||||
overwrite("warn");
|
||||
overwrite("error");
|
||||
}
|
||||
|
||||
window.debug.console.overwriteNativeIfRequired = function() {
|
||||
|
@ -14,6 +14,7 @@ window.setupGeosearch = function() {
|
||||
$('#geosearchwrapper img').click(function(){
|
||||
map.locate({setView : true, maxZoom: 13});
|
||||
});
|
||||
$('#geosearch').keyup(function(){$(this).removeClass('search_not_found')});
|
||||
}
|
||||
|
||||
window.search = function(search) {
|
||||
@ -22,13 +23,16 @@ window.search = function(search) {
|
||||
}
|
||||
|
||||
$.getJSON(NOMINATIM + encodeURIComponent(search), function(data) {
|
||||
if(!data || !data[0]) return true;
|
||||
if(!data || !data[0]) {
|
||||
$('#geosearch').addClass('search_not_found');
|
||||
return true;
|
||||
}
|
||||
var b = data[0].boundingbox;
|
||||
if(!b) return true;
|
||||
var southWest = new L.LatLng(b[0], b[2]),
|
||||
northEast = new L.LatLng(b[1], b[3]),
|
||||
bounds = new L.LatLngBounds(southWest, northEast);
|
||||
window.map.fitBounds(bounds);
|
||||
if(window.isSmartphone()) window.smartphone.mapButton.click();
|
||||
if(window.isSmartphone()) window.show('map');
|
||||
});
|
||||
}
|
||||
|
@ -15,6 +15,9 @@
|
||||
// required to successfully boot the plugin.
|
||||
//
|
||||
// Here’s more specific information about each event:
|
||||
// playerNameResolved: called when unresolved player name get resolved.
|
||||
// Argument is {names: object} which names[guid] is the
|
||||
// resolved player name.
|
||||
// portalSelected: called when portal on map is selected/unselected.
|
||||
// Provide guid of selected and unselected portal.
|
||||
// mapDataRefreshStart: called when we start refreshing map data
|
||||
@ -49,7 +52,7 @@
|
||||
|
||||
window._hooks = {}
|
||||
window.VALID_HOOKS = [
|
||||
'portalSelected',
|
||||
'playerNameResolved', 'portalSelected',
|
||||
'mapDataRefreshStart', 'mapDataRefreshEnd',
|
||||
'portalAdded', 'linkAdded', 'fieldAdded',
|
||||
'portalDetailsUpdated',
|
||||
|
@ -2,8 +2,16 @@
|
||||
// cache for map data tiles.
|
||||
|
||||
window.DataCache = function() {
|
||||
this.REQUEST_CACHE_FRESH_AGE = 60; // if younger than this, use data in the cache rather than fetching from the server
|
||||
this.REQUEST_CACHE_MAX_AGE = 180; // maximum cache age. entries are deleted from the cache after this time
|
||||
// stock site nemesis.dashboard.DataManager.CACHE_EXPIRY_MS_ = 18E4 - so should be 2 mins cache time
|
||||
this.REQUEST_CACHE_FRESH_AGE = 120; // if younger than this, use data in the cache rather than fetching from the server
|
||||
|
||||
// stale cache entries can be updated (that's what the optional 'timestampMs' field in getThinnedEntnties is
|
||||
// for, retrieving deltas) so use a long max age to take advantage of this
|
||||
// however, ther must be an overall limit on the maximum age of data from the servers, otherwise the deletedEntity
|
||||
// entries would grow indefinitely. an hour seems reasonable from experience with the data, so 55 mins max cache time
|
||||
// this.REQUEST_CACHE_MAX_AGE = 55*60; // maximum cache age. entries are deleted from the cache after this time
|
||||
//UPDATE: this timestampMs parameter doesn't work, so reduced max age to limit RAM usage
|
||||
this.REQUEST_CACHE_MAX_AGE = 15*60; // maximum cache age. entries are deleted from the cache after this time
|
||||
|
||||
if (L.Browser.mobile) {
|
||||
// on mobile devices, smaller cache size
|
||||
@ -18,15 +26,19 @@ window.DataCache = function() {
|
||||
|
||||
}
|
||||
|
||||
window.DataCache.prototype.store = function(qk,data,date) {
|
||||
window.DataCache.prototype.store = function(qk,data,freshTime) {
|
||||
// fixme? common behaviour for objects is that properties are kept in the order they're added
|
||||
// this is handy, as it allows easy retrieval of the oldest entries for expiring
|
||||
// however, this is not guaranteed by the standards, but all our supported browsers work this way
|
||||
|
||||
delete this._cache[qk];
|
||||
|
||||
if (date === undefined) date = new Date();
|
||||
this._cache[qk] = { time: date.getTime(), data: data };
|
||||
var time = new Date().getTime();
|
||||
|
||||
if (freshTime===undefined) freshTime = this.REQUEST_CACHE_FRESH_AGE*1000;
|
||||
var expire = time + freshTime;
|
||||
|
||||
this._cache[qk] = { time: time, expire: expire, data: data };
|
||||
}
|
||||
|
||||
window.DataCache.prototype.get = function(qk) {
|
||||
@ -42,8 +54,8 @@ window.DataCache.prototype.getTime = function(qk) {
|
||||
window.DataCache.prototype.isFresh = function(qk) {
|
||||
if (qk in this._cache) {
|
||||
var d = new Date();
|
||||
var t = d.getTime() - this.REQUEST_CACHE_FRESH_AGE*1000;
|
||||
if (this._cache[qk].time >= t) return true;
|
||||
var t = d.getTime();
|
||||
if (this._cache[qk].expire >= t) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
@ -9,26 +9,33 @@
|
||||
// Convertion functions courtesy of
|
||||
// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
|
||||
|
||||
window.lngToTile = function(lng, zoom) {
|
||||
return Math.floor((lng + 180) / 360 * Math.pow(2, (zoom>12)?zoom:(zoom+2)));
|
||||
|
||||
window.levelToTilesPerEdge = function(level) {
|
||||
var LEVEL_TO_TILES_PER_EDGE = [65536, 65536, 16384, 16384, 4096, 1536, 1024, 256, 32];
|
||||
return LEVEL_TO_TILES_PER_EDGE[level];
|
||||
}
|
||||
|
||||
window.latToTile = function(lat, zoom) {
|
||||
|
||||
window.lngToTile = function(lng, level) {
|
||||
return Math.floor((lng + 180) / 360 * levelToTilesPerEdge(level));
|
||||
}
|
||||
|
||||
window.latToTile = function(lat, level) {
|
||||
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>12)?zoom:(zoom+2)));
|
||||
1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * levelToTilesPerEdge(level));
|
||||
}
|
||||
|
||||
window.tileToLng = function(x, zoom) {
|
||||
return x / Math.pow(2, (zoom>12)?zoom:(zoom+2)) * 360 - 180;
|
||||
window.tileToLng = function(x, level) {
|
||||
return x / levelToTilesPerEdge(level) * 360 - 180;
|
||||
}
|
||||
|
||||
window.tileToLat = function(y, zoom) {
|
||||
var n = Math.PI - 2 * Math.PI * y / Math.pow(2, (zoom>12)?zoom:(zoom+2));
|
||||
window.tileToLat = function(y, level) {
|
||||
var n = Math.PI - 2 * Math.PI * y / levelToTilesPerEdge(level);
|
||||
return 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
|
||||
}
|
||||
|
||||
window.pointToTileId = function(zoom, x, y) {
|
||||
return zoom + "_" + x + "_" + y;
|
||||
window.pointToTileId = function(level, x, y) {
|
||||
return level + "_" + x + "_" + y;
|
||||
}
|
||||
|
||||
// given tile id and bounds, returns the format as required by the
|
||||
|
@ -192,7 +192,9 @@ window.Render.prototype.deletePortalEntity = function(guid) {
|
||||
window.Render.prototype.deleteLinkEntity = function(guid) {
|
||||
if (guid in window.links) {
|
||||
var l = window.links[guid];
|
||||
linksFactionLayers[l.options.team].removeLayer(l);
|
||||
if (linksFactionLayers[l.options.team].hasLayer(l)) {
|
||||
linksFactionLayers[l.options.team].removeLayer(l);
|
||||
}
|
||||
delete window.links[guid];
|
||||
}
|
||||
}
|
||||
|
@ -28,24 +28,27 @@ window.MapDataRequest = function() {
|
||||
this.MAX_TILE_RETRIES = 3;
|
||||
|
||||
// refresh timers
|
||||
this.MOVE_REFRESH = 0.5; //refresh time to use after a move
|
||||
this.STARTUP_REFRESH = 5; //refresh time used on first load of IITC
|
||||
this.MOVE_REFRESH = 1; //time, after a map move (pan/zoom) before starting the refresh processing
|
||||
this.STARTUP_REFRESH = 3; //refresh time used on first load of IITC
|
||||
this.IDLE_RESUME_REFRESH = 5; //refresh time used after resuming from idle
|
||||
|
||||
// after one of the above, there's an additional delay between preparing the refresh (clearing out of bounds,
|
||||
// processing cache, etc) and actually sending the first network requests
|
||||
this.DOWNLOAD_DELAY = 3; //delay after preparing the data download before tile requests are sent
|
||||
|
||||
// a short delay between one request finishing and the queue being run for the next request
|
||||
|
||||
// a short delay between one request finishing and the queue being run for the next request.
|
||||
// this gives a chance of other requests finishing, allowing better grouping of retries in new requests
|
||||
this.RUN_QUEUE_DELAY = 0.5;
|
||||
|
||||
// delay before re-queueing tiles
|
||||
this.TILE_TIMEOUT_REQUEUE_DELAY = 0.5; // short delay before retrying a 'error==TIMEOUT' tile - as this is very common
|
||||
this.BAD_REQUEST_REQUEUE_DELAY = 4; // longer delay before retrying a completely failed request - as in this case the servers are struggling
|
||||
// delay before re-queueing tiles in failed requests
|
||||
this.BAD_REQUEST_REQUEUE_DELAY = 5; // longer delay before retrying a completely failed request - as in this case the servers are struggling
|
||||
|
||||
// a delay before processing the queue after requeueing tiles. this gives a chance for other requests to finish
|
||||
// or other requeue actions to happen before the queue is processed, allowing better grouping of requests
|
||||
// however, the queue may be processed sooner if a previous timeout was set
|
||||
this.REQUEUE_DELAY = 1;
|
||||
|
||||
// additionally, a delay before processing the queue after requeueing tiles
|
||||
// (this way, if multiple requeue delays finish within a short time of each other, they're all processed in one queue run)
|
||||
this.RERUN_QUEUE_DELAY = 2;
|
||||
|
||||
this.REFRESH_CLOSE = 120; // refresh time to use for close views z>12 when not idle and not moving
|
||||
this.REFRESH_FAR = 600; // refresh time for far views z <= 12
|
||||
@ -89,8 +92,8 @@ window.MapDataRequest.prototype.mapMoveEnd = function() {
|
||||
|
||||
if (this.fetchedDataParams) {
|
||||
// we have fetched (or are fetching) data...
|
||||
if (this.fetchedDataParams.zoom == zoom && this.fetchedDataParams.bounds.contains(bounds)) {
|
||||
// ... and the data zoom levels are the same, and the current bounds is inside the fetched bounds
|
||||
if (this.fetchedDataParams.mapZoom == map.getZoom() && this.fetchedDataParams.bounds.contains(bounds)) {
|
||||
// ... and the zoom level is the same and the current bounds is inside the fetched bounds
|
||||
// so, no need to fetch data. if there's time left, restore the original timeout
|
||||
|
||||
var remainingTime = (this.timerExpectedTimeoutTime - new Date().getTime())/1000;
|
||||
@ -169,8 +172,8 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
// a 'set' to keep track of hard failures for tiles
|
||||
this.tileErrorCount = {};
|
||||
|
||||
// fill tileBounds with the data needed to request each tile
|
||||
this.tileBounds = {};
|
||||
// the 'set' of requested tile QKs
|
||||
this.queuedTiles = {};
|
||||
|
||||
|
||||
var bounds = clampLatLngBounds(map.getBounds());
|
||||
@ -183,24 +186,24 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
//var debugrect = L.rectangle(bounds,{color: 'red', fill: false, weight: 4, opacity: 0.8}).addTo(map);
|
||||
//setTimeout (function(){ map.removeLayer(debugrect); }, 10*1000);
|
||||
|
||||
var x1 = lngToTile(bounds.getWest(), zoom);
|
||||
var x2 = lngToTile(bounds.getEast(), zoom);
|
||||
var y1 = latToTile(bounds.getNorth(), zoom);
|
||||
var y2 = latToTile(bounds.getSouth(), zoom);
|
||||
var x1 = lngToTile(bounds.getWest(), minPortalLevel);
|
||||
var x2 = lngToTile(bounds.getEast(), minPortalLevel);
|
||||
var y1 = latToTile(bounds.getNorth(), minPortalLevel);
|
||||
var y2 = latToTile(bounds.getSouth(), minPortalLevel);
|
||||
|
||||
// calculate the full bounds for the data - including the part of the tiles off the screen edge
|
||||
var dataBounds = L.latLngBounds([
|
||||
[tileToLat(y2+1,zoom), tileToLng(x1,zoom)],
|
||||
[tileToLat(y1,zoom), tileToLng(x2+1,zoom)]
|
||||
[tileToLat(y2+1,minPortalLevel), tileToLng(x1,minPortalLevel)],
|
||||
[tileToLat(y1,minPortalLevel), tileToLng(x2+1,minPortalLevel)]
|
||||
]);
|
||||
//var debugrect2 = L.rectangle(dataBounds,{color: 'magenta', fill: false, weight: 4, opacity: 0.8}).addTo(map);
|
||||
//setTimeout (function(){ map.removeLayer(debugrect2); }, 10*1000);
|
||||
|
||||
// store the parameters used for fetching the data. used to prevent unneeded refreshes after move/zoom
|
||||
this.fetchedDataParams = { bounds: dataBounds, zoom: zoom };
|
||||
this.fetchedDataParams = { bounds: dataBounds, mapZoom: map.getZoom(), minPortalLevel: minPortalLevel };
|
||||
|
||||
|
||||
window.runHooks ('mapDataRefreshStart', {bounds: bounds, zoom: zoom, tileBounds: dataBounds});
|
||||
window.runHooks ('mapDataRefreshStart', {bounds: bounds, zoom: zoom, minPortalLevel: minPortalLevel, tileBounds: dataBounds});
|
||||
|
||||
this.render.startRenderPass();
|
||||
this.render.clearPortalsBelowLevel(minPortalLevel);
|
||||
@ -224,11 +227,11 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
for (var y = y1; y <= y2; y++) {
|
||||
// x goes from bottom to top(?)
|
||||
for (var x = x1; x <= x2; x++) {
|
||||
var tile_id = pointToTileId(zoom, x, y);
|
||||
var latNorth = tileToLat(y,zoom);
|
||||
var latSouth = tileToLat(y+1,zoom);
|
||||
var lngWest = tileToLng(x,zoom);
|
||||
var lngEast = tileToLng(x+1,zoom);
|
||||
var tile_id = pointToTileId(minPortalLevel, x, y);
|
||||
var latNorth = tileToLat(y,minPortalLevel);
|
||||
var latSouth = tileToLat(y+1,minPortalLevel);
|
||||
var lngWest = tileToLng(x,minPortalLevel);
|
||||
var lngEast = tileToLng(x+1,minPortalLevel);
|
||||
|
||||
this.debugTiles.create(tile_id,[[latSouth,lngWest],[latNorth,lngEast]]);
|
||||
|
||||
@ -238,16 +241,17 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
this.render.processTileData (this.cache.get(tile_id));
|
||||
this.cachedTileCount += 1;
|
||||
} else {
|
||||
// no fresh data - queue a request
|
||||
var boundsParams = generateBoundsParams(
|
||||
tile_id,
|
||||
latSouth,
|
||||
lngWest,
|
||||
latNorth,
|
||||
lngEast
|
||||
);
|
||||
|
||||
this.tileBounds[tile_id] = boundsParams;
|
||||
// no fresh data
|
||||
|
||||
// render the cached stale data, if we have it. this ensures *something* appears quickly when possible
|
||||
var old_data = this.cache && this.cache.get(tile_id);
|
||||
if (old_data) {
|
||||
this.render.processTileData (old_data);
|
||||
}
|
||||
|
||||
// queue a request
|
||||
this.queuedTiles[tile_id] = tile_id;
|
||||
this.requestedTileCount += 1;
|
||||
}
|
||||
}
|
||||
@ -255,10 +259,19 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
|
||||
this.setStatus ('loading');
|
||||
|
||||
// technically a request hasn't actually finished - however, displayed portal data has been refreshed
|
||||
// so as far as plugins are concerned, it should be treated as a finished request
|
||||
window.runHooks('requestFinished', {success: true});
|
||||
|
||||
console.log ('done request preperation (cleared out-of-bounds and invalid for zoom, and rendered cached data)');
|
||||
|
||||
// don't start processing the download queue immediately - start it after a short delay
|
||||
this.delayProcessRequestQueue (this.DOWNLOAD_DELAY,true);
|
||||
if (Object.keys(this.queuedTiles).length > 0) {
|
||||
// queued requests - don't start processing the download queue immediately - start it after a short delay
|
||||
this.delayProcessRequestQueue (this.DOWNLOAD_DELAY,true);
|
||||
} else {
|
||||
// all data was from the cache, nothing queued - run the queue 'immediately' so it handles the end request processing
|
||||
this.delayProcessRequestQueue (0,true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -273,7 +286,7 @@ window.MapDataRequest.prototype.delayProcessRequestQueue = function(seconds,isFi
|
||||
window.MapDataRequest.prototype.processRequestQueue = function(isFirstPass) {
|
||||
|
||||
// if nothing left in the queue, end the render. otherwise, send network requests
|
||||
if (Object.keys(this.tileBounds).length == 0) {
|
||||
if (Object.keys(this.queuedTiles).length == 0) {
|
||||
|
||||
this.render.endRenderPass();
|
||||
|
||||
@ -301,7 +314,7 @@ window.MapDataRequest.prototype.processRequestQueue = function(isFirstPass) {
|
||||
|
||||
// create a list of tiles that aren't requested over the network
|
||||
var pendingTiles = [];
|
||||
for (var id in this.tileBounds) {
|
||||
for (var id in this.queuedTiles) {
|
||||
if (!(id in this.requestedTiles) ) {
|
||||
pendingTiles.push(id);
|
||||
}
|
||||
@ -351,7 +364,7 @@ window.MapDataRequest.prototype.processRequestQueue = function(isFirstPass) {
|
||||
|
||||
window.MapDataRequest.prototype.sendTileRequest = function(tiles) {
|
||||
|
||||
var boundsParamsList = [];
|
||||
var tilesList = [];
|
||||
|
||||
for (var i in tiles) {
|
||||
var id = tiles[i];
|
||||
@ -360,15 +373,14 @@ window.MapDataRequest.prototype.sendTileRequest = function(tiles) {
|
||||
|
||||
this.requestedTiles[id] = true;
|
||||
|
||||
var boundsParams = this.tileBounds[id];
|
||||
if (boundsParams) {
|
||||
boundsParamsList.push (boundsParams);
|
||||
if (id in this.queuedTiles) {
|
||||
tilesList.push (id);
|
||||
} else {
|
||||
console.warn('failed to find bounds for tile id '+id);
|
||||
console.warn('no queue entry for tile id '+id);
|
||||
}
|
||||
}
|
||||
|
||||
var data = { boundsParamsList: boundsParamsList };
|
||||
var data = { quadKeys: tilesList };
|
||||
|
||||
this.activeRequestCount += 1;
|
||||
|
||||
@ -382,7 +394,7 @@ window.MapDataRequest.prototype.sendTileRequest = function(tiles) {
|
||||
}
|
||||
|
||||
window.MapDataRequest.prototype.requeueTile = function(id, error) {
|
||||
if (id in this.tileBounds) {
|
||||
if (id in this.queuedTiles) {
|
||||
// tile is currently wanted...
|
||||
|
||||
// first, see if the error can be ignored due to retry counts
|
||||
@ -408,7 +420,7 @@ window.MapDataRequest.prototype.requeueTile = function(id, error) {
|
||||
this.failedTileCount += 1;
|
||||
}
|
||||
// and delete from the pending requests...
|
||||
delete this.tileBounds[id];
|
||||
delete this.queuedTiles[id];
|
||||
|
||||
} else {
|
||||
// if false, was a 'timeout' or we're retrying, so unlimited retries (as the stock site does)
|
||||
@ -418,9 +430,8 @@ window.MapDataRequest.prototype.requeueTile = function(id, error) {
|
||||
// proper queue, just an object with guid as properties. Javascript standards don't guarantee the order of properties
|
||||
// within an object. however, all current browsers do keep property order, and new properties are added at the end.
|
||||
// therefore, delete and re-add the requeued tile and it will be added to the end of the queue
|
||||
var boundsData = this.tileBounds[id];
|
||||
delete this.tileBounds[id];
|
||||
this.tileBounds[id] = boundsData;
|
||||
delete this.queuedTiles[id];
|
||||
this.queuedTiles[id] = id;
|
||||
|
||||
}
|
||||
} // else the tile wasn't currently wanted (an old non-cancelled request) - ignore
|
||||
@ -463,7 +474,6 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
|
||||
if (val.error == "TIMEOUT") {
|
||||
// TIMEOUT errors for individual tiles are 'expected'(!) - and result in a silent unlimited retries
|
||||
timeoutTiles.push (id);
|
||||
this.debugTiles.setState (id, 'tile-timeout');
|
||||
} else {
|
||||
console.warn('map data tile '+id+' failed: error=='+val.error);
|
||||
errorTiles.push (id);
|
||||
@ -478,12 +488,12 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
|
||||
|
||||
// if this tile was in the render list, render it
|
||||
// (requests aren't aborted when new requests are started, so it's entirely possible we don't want to render it!)
|
||||
if (id in this.tileBounds) {
|
||||
if (id in this.queuedTiles) {
|
||||
this.debugTiles.setState (id, 'ok');
|
||||
|
||||
this.render.processTileData (val);
|
||||
|
||||
delete this.tileBounds[id];
|
||||
delete this.queuedTiles[id];
|
||||
this.successTileCount += 1;
|
||||
|
||||
} // else we don't want this tile (from an old non-cancelled request) - ignore
|
||||
@ -491,6 +501,9 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
|
||||
|
||||
}
|
||||
|
||||
// TODO? check for any requested tiles in 'tiles' not being mentioned in the response - and handle as if it's a 'timeout'?
|
||||
|
||||
|
||||
window.runHooks('requestFinished', {success: true});
|
||||
}
|
||||
|
||||
@ -498,28 +511,27 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
|
||||
console.log ('getThinnedEntities status: '+tiles.length+' tiles: '+successTiles.length+' successful, '+timeoutTiles.length+' timed out, '+errorTiles.length+' failed');
|
||||
|
||||
|
||||
//setTimeout has no way of passing the 'context' (aka 'this') to it's function
|
||||
var savedContext = this;
|
||||
|
||||
// requeue any 'timeout' tiles immediately
|
||||
if (timeoutTiles.length > 0) {
|
||||
setTimeout (function() {
|
||||
for (var i in timeoutTiles) {
|
||||
var id = timeoutTiles[i];
|
||||
delete savedContext.requestedTiles[id];
|
||||
savedContext.requeueTile(id, false);
|
||||
}
|
||||
savedContext.delayProcessRequestQueue(this.RERUN_QUEUE_DELAY);
|
||||
}, this.TILE_TIMEOUT_REQUEUE_DELAY*1000);
|
||||
for (var i in timeoutTiles) {
|
||||
var id = timeoutTiles[i];
|
||||
delete this.requestedTiles[id];
|
||||
this.requeueTile(id, false);
|
||||
}
|
||||
}
|
||||
|
||||
// but for other errors, delay before retrying (as the server is having issues)
|
||||
if (errorTiles.length > 0) {
|
||||
//setTimeout has no way of passing the 'context' (aka 'this') to it's function
|
||||
var savedContext = this;
|
||||
|
||||
setTimeout (function() {
|
||||
for (var i in errorTiles) {
|
||||
var id = errorTiles[i];
|
||||
delete savedContext.requestedTiles[id];
|
||||
savedContext.requeueTile(id, true);
|
||||
}
|
||||
savedContext.delayProcessRequestQueue(this.RERUN_QUEUE_DELAY);
|
||||
savedContext.delayProcessRequestQueue(this.REQUEUE_DELAY);
|
||||
}, this.BAD_REQUEST_REQUEUE_DELAY*1000);
|
||||
}
|
||||
|
||||
|
@ -1,42 +1,45 @@
|
||||
// created to start cleaning up "window" interaction
|
||||
//
|
||||
window.show = function(id) {
|
||||
window.hideall();
|
||||
if (typeof android !== 'undefined' && android && android.switchToPane) {
|
||||
android.switchToPane(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();
|
||||
$('#portal_highlight_select').show();
|
||||
$('#farm_level_select').show();
|
||||
break;
|
||||
case 'info':
|
||||
window.smartphone.sideButton.click();
|
||||
break;
|
||||
default:
|
||||
window.smartphone.mapButton.click();
|
||||
break;
|
||||
}
|
||||
window.hideall();
|
||||
|
||||
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();
|
||||
$('#portal_highlight_select').show();
|
||||
$('#farm_level_select').show();
|
||||
break;
|
||||
case 'info':
|
||||
window.smartphone.sideButton.click();
|
||||
break;
|
||||
default:
|
||||
window.smartphone.mapButton.click();
|
||||
break;
|
||||
}
|
||||
|
||||
if (typeof android !== 'undefined' && android && android.switchToPane) {
|
||||
android.switchToPane(id);
|
||||
}
|
||||
}
|
||||
|
||||
window.hideall = function() {
|
||||
$('#chatcontrols, #chat, #chatinput, #sidebartoggle, #scrollwrapper, #updatestatus, #portal_highlight_select').hide();
|
||||
$('#farm_level_select').hide();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
$('#chatcontrols, #chat, #chatinput, #sidebartoggle, #scrollwrapper, #updatestatus, #portal_highlight_select').hide();
|
||||
$('#farm_level_select').hide();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
$('.ui-tooltip').remove();
|
||||
}
|
||||
|
@ -39,6 +39,12 @@ window.playerNameToGuid = function(playerName) {
|
||||
var cachedGuid = window._playerNameToGuidCache[playerName];
|
||||
if (cachedGuid !== undefined) return cachedGuid;
|
||||
|
||||
// IITC needs our own player GUID, from a lookup by name. so we retrieve this from localstorage (if available)
|
||||
if (playerName == PLAYER.nickname) {
|
||||
cachedGuid = localStorage['PLAYER-'+PLAYER.nickname];
|
||||
if (cachedGuid !== undefined) return cachedGuid;
|
||||
}
|
||||
|
||||
var guid = null;
|
||||
$.each(Object.keys(sessionStorage), function(ind,key) {
|
||||
if(playerName === sessionStorage[key]) {
|
||||
@ -68,9 +74,11 @@ window.resolvePlayerNames = function() {
|
||||
window.playersInResolving = window.playersInResolving.concat(p);
|
||||
|
||||
postAjax('getPlayersByGuids', d, function(dat) {
|
||||
var resolvedName = {};
|
||||
if(dat.result) {
|
||||
$.each(dat.result, function(ind, player) {
|
||||
window.setPlayerName(player.guid, player.nickname);
|
||||
resolvedName[player.guid] = player.nickname;
|
||||
// remove from array
|
||||
window.playersInResolving.splice(window.playersInResolving.indexOf(player.guid), 1);
|
||||
});
|
||||
@ -82,6 +90,9 @@ window.resolvePlayerNames = function() {
|
||||
//therefore, not a good idea to automatically retry by adding back to the playersToResolve list
|
||||
}
|
||||
|
||||
// Run hook 'playerNameResolved' with the resolved player names
|
||||
window.runHooks('playerNameResolved', {names: resolvedName});
|
||||
|
||||
//TODO: have an event triggered for this instead of hard-coded single function call
|
||||
if(window.selectedPortal)
|
||||
window.renderPortalDetails(window.selectedPortal);
|
||||
@ -107,22 +118,17 @@ window.setPlayerName = function(guid, nick, uncertain) {
|
||||
alert('You have run into bug #37. Please help me solve it!\nCopy and paste this text and post it here:\nhttps://github.com/breunigs/ingress-intel-total-conversion/issues/37\nIf copy & pasting doesn’t work, make a screenshot instead.\n\n\n' + window.debug.printStackTrace() + '\n\n\n' + JSON.stringify(nick));
|
||||
}
|
||||
sessionStorage[guid] = nick;
|
||||
|
||||
// IITC needs our own player ID early on in startup. the only way we can find this is by something else
|
||||
// doing a guid->name lookup for our own name. as this doesn't always happen - and likely won't happen when needed
|
||||
// we'll store our own name->guid lookup in localStorage
|
||||
if (nick == PLAYER.nickname) {
|
||||
localStorage['PLAYER-'+PLAYER.nickname] = guid;
|
||||
PLAYER.guid = guid; // set it in PLAYER in case it wasn't already done
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
window.loadPlayerNamesForPortal = function(portal_details) {
|
||||
if(map.getZoom() < PRECACHE_PLAYER_NAMES_ZOOM) return;
|
||||
var e = portal_details;
|
||||
|
||||
if(e.captured && e.captured.capturingPlayerId)
|
||||
getPlayerName(e.captured.capturingPlayerId);
|
||||
|
||||
if(!e.resonatorArray || !e.resonatorArray.resonators) return;
|
||||
|
||||
$.each(e.resonatorArray.resonators, function(ind, reso) {
|
||||
if(reso) getPlayerName(reso.ownerGuid);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// test to see if a specific player GUID is a special system account (e.g. __JARVIS__, __ADA__) that shouldn't
|
||||
|
@ -90,6 +90,17 @@ window.renderPortalDetails = function(guid) {
|
||||
portalDetailedDescription += '</table>';
|
||||
}
|
||||
|
||||
var levelDetails = getPortalLevel(d);
|
||||
if(levelDetails != 8) {
|
||||
if(levelDetails==Math.ceil(levelDetails))
|
||||
levelDetails += "\n8";
|
||||
else
|
||||
levelDetails += "\n" + (Math.ceil(levelDetails) - levelDetails)*8;
|
||||
levelDetails += " resonator level(s) needed for next portal level";
|
||||
} else {
|
||||
levelDetails += "\nfully upgraded";
|
||||
}
|
||||
levelDetails = "Level " + levelDetails;
|
||||
|
||||
$('#portaldetails')
|
||||
.attr('class', TEAM_TO_CSS[getTeam(d)])
|
||||
@ -98,7 +109,7 @@ window.renderPortalDetails = function(guid) {
|
||||
+ '<span class="close" onclick="renderPortalDetails(null); if(isSmartphone()) show(\'map\');" title="Close">X</span>'
|
||||
// help cursor via ".imgpreview img"
|
||||
+ '<div class="imgpreview" '+imgTitle+' style="background-image: url('+img+')">'
|
||||
+ '<span id="level">'+Math.floor(getPortalLevel(d))+'</span>'
|
||||
+ '<span id="level" title="'+levelDetails+'">'+Math.floor(getPortalLevel(d))+'</span>'
|
||||
+ '<div class="portalDetails">'+ portalDetailedDescription + '</div>'
|
||||
+ '<img class="hide" src="'+img+'"/></div>'
|
||||
+ '</div>'
|
||||
@ -134,9 +145,14 @@ window.setPortalIndicators = function(d) {
|
||||
|
||||
var range = getPortalRange(d);
|
||||
var coord = [d.locationE6.latE6/1E6, d.locationE6.lngE6/1E6];
|
||||
portalRangeIndicator = (range > 0
|
||||
? L.geodesicCircle(coord, range, { fill: false, color: RANGE_INDICATOR_COLOR, weight: 3, clickable: false })
|
||||
: L.circle(coord, range, { fill: false, stroke: false, clickable: false })
|
||||
portalRangeIndicator = (range.range > 0
|
||||
? L.geodesicCircle(coord, range.range, {
|
||||
fill: false,
|
||||
color: RANGE_INDICATOR_COLOR,
|
||||
weight: 3,
|
||||
dashArray: range.isLinkable ? undefined : "10,10",
|
||||
clickable: false })
|
||||
: L.circle(coord, range.range, { fill: false, stroke: false, clickable: false })
|
||||
).addTo(map);
|
||||
|
||||
portalAccessIndicator = L.circle(coord, HACK_RANGE,
|
||||
|
@ -5,11 +5,20 @@
|
||||
// returns displayable text+link about portal range
|
||||
window.getRangeText = function(d) {
|
||||
var range = getPortalRange(d);
|
||||
|
||||
var title = 'Base range:\t' + digits(Math.floor(range.base))+'m'
|
||||
+ '\nLink amp boost:\t×'+range.boost
|
||||
+ '\nRange:\t'+digits(Math.floor(range.range))+'m';
|
||||
|
||||
if(!range.isLinkable) title += '\nPortal is missing resonators,\nno new links can be made';
|
||||
|
||||
return ['range',
|
||||
'<a onclick="window.rangeLinkClick()">'
|
||||
+ (range > 1000
|
||||
? Math.floor(range/1000) + ' km'
|
||||
: Math.floor(range) + ' m')
|
||||
'<a onclick="window.rangeLinkClick()"'
|
||||
+ (range.isLinkable ? '' : ' style="text-decoration:line-through;"')
|
||||
+ ' title="'+title+'">'
|
||||
+ (range.range > 1000
|
||||
? Math.floor(range.range/1000) + ' km'
|
||||
: Math.floor(range.range) + ' m')
|
||||
+ '</a>'];
|
||||
}
|
||||
|
||||
|
@ -47,18 +47,20 @@ window.getPortalRange = function(d) {
|
||||
$.each(d.resonatorArray.resonators, function(ind, reso) {
|
||||
if(!reso) {
|
||||
resoMissing = true;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
lvl += parseInt(reso.level);
|
||||
});
|
||||
if(resoMissing) return 0;
|
||||
|
||||
var range = 160*Math.pow(getPortalLevel(d), 4);
|
||||
var range = {
|
||||
base: 160*Math.pow(getPortalLevel(d), 4),
|
||||
boost: getLinkAmpRangeBoost(d)
|
||||
};
|
||||
|
||||
var boost = getLinkAmpRangeBoost(d);
|
||||
|
||||
return range*boost;
|
||||
range.range = range.boost * range.base;
|
||||
range.isLinkable = !resoMissing;
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
window.getLinkAmpRangeBoost = function(d) {
|
||||
|
@ -35,7 +35,6 @@ window.runOnSmartphonesBeforeBoot = function() {
|
||||
}
|
||||
|
||||
window.smartphone.mapButton = $('<a>map</a>').click(function() {
|
||||
$('#chat, #chatinput, #scrollwrapper').hide();
|
||||
$('#map').css('visibility', 'visible');
|
||||
$('#updatestatus').show();
|
||||
$('#chatcontrols a .active').removeClass('active');
|
||||
@ -43,8 +42,6 @@ window.runOnSmartphonesBeforeBoot = function() {
|
||||
});
|
||||
|
||||
window.smartphone.sideButton = $('<a>info</a>').click(function() {
|
||||
$('#chat, #chatinput, #updatestatus').hide();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
$('#scrollwrapper').show();
|
||||
$('.active').removeClass('active');
|
||||
$("#chatcontrols a:contains('info')").addClass('active');
|
||||
@ -112,11 +109,13 @@ window.runOnSmartphonesAfterBoot = function() {
|
||||
if(!isSmartphone()) return;
|
||||
console.warn('running smartphone post boot stuff');
|
||||
|
||||
smartphone.mapButton.click();
|
||||
window.show('map');
|
||||
|
||||
// add a div/hook for updating mobile info
|
||||
$('#updatestatus').prepend('<div id="mobileinfo" onclick="show(\'info\')"></div>');
|
||||
window.addHook('portalDetailsUpdated', window.smartphoneInfo);
|
||||
// init msg of status bar. hint for the user that a tap leads to the info screen
|
||||
$('#mobileinfo').html('<div style="text-align: center"><b>tap here for info screen</b></div>');
|
||||
|
||||
// disable img full view
|
||||
$('#portaldetails').off('click', '**');
|
||||
|
@ -1,597 +0,0 @@
|
||||
// UTILS + MISC ///////////////////////////////////////////////////////
|
||||
|
||||
window.aboutIITC = function(){
|
||||
var v = '@@BUILDNAME@@-@@BUILDDATE@@';
|
||||
var attrib = '@@INCLUDEMD:ATTRIBUTION.md@@';
|
||||
var contrib = '@@INCLUDEMD:CONTRIBS.md@@'
|
||||
var a = ''
|
||||
+ ' <div><b>About IITC</b></div> '
|
||||
+ ' <div>Ingress Intel Total Conversion</div> '
|
||||
+ ' <hr>'
|
||||
+ ' <div>'
|
||||
+ ' <a href="http://iitc.jonatkins.com/" target="_blank">IITC Homepage</a><br />'
|
||||
+ ' On the script’s homepage you can:'
|
||||
+ ' <ul>'
|
||||
+ ' <li>Find Updates</li>'
|
||||
+ ' <li>Get Plugins</li>'
|
||||
+ ' <li>Report Bugs</li>'
|
||||
+ ' <li>Contribute!</li>'
|
||||
+ ' </ul>'
|
||||
+ ' </div>'
|
||||
+ ' <div>'
|
||||
+ ' MapQuest OSM tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="https://developer.mapquest.com/content/osm/mq_logo.png">'
|
||||
+ ' </div>'
|
||||
+ ' <hr>'
|
||||
+ ' <div>Version: ' + v + '</div>'
|
||||
+ ' <hr>'
|
||||
+ ' <div>' + attrib + '</div>'
|
||||
+ ' <hr>'
|
||||
+ ' <div>' + contrib + '</div>';
|
||||
dialog({
|
||||
title: 'IITC ' + v,
|
||||
html: a,
|
||||
dialogClass: 'ui-dialog-aboutIITC'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
window.layerGroupLength = function(layerGroup) {
|
||||
var layersCount = 0;
|
||||
var layers = layerGroup._layers;
|
||||
if (layers)
|
||||
layersCount = Object.keys(layers).length;
|
||||
return layersCount;
|
||||
}
|
||||
|
||||
// retrieves parameter from the URL?query=string.
|
||||
window.getURLParam = function(param) {
|
||||
var v = document.URL;
|
||||
var i = v.indexOf(param);
|
||||
if(i <= -1) return '';
|
||||
v = v.substr(i);
|
||||
i = v.indexOf("&");
|
||||
if(i >= 0) v = v.substr(0, i);
|
||||
return v.replace(param+"=","");
|
||||
}
|
||||
|
||||
// read cookie by name.
|
||||
// http://stackoverflow.com/a/5639455/1684530 by cwolves
|
||||
var cookies;
|
||||
window.readCookie = function(name,c,C,i){
|
||||
if(cookies) return cookies[name];
|
||||
c = document.cookie.split('; ');
|
||||
cookies = {};
|
||||
for(i=c.length-1; i>=0; i--){
|
||||
C = c[i].split('=');
|
||||
cookies[C[0]] = unescape(C[1]);
|
||||
}
|
||||
return cookies[name];
|
||||
}
|
||||
|
||||
window.writeCookie = function(name, val) {
|
||||
document.cookie = name + "=" + val + '; expires=Thu, 31 Dec 2020 23:59:59 GMT; path=/';
|
||||
}
|
||||
|
||||
window.eraseCookie = function(name) {
|
||||
document.cookie = name + '=; expires=Thu, 1 Jan 1970 00:00:00 GMT; path=/';
|
||||
}
|
||||
|
||||
//certain values were stored in cookies, but we're better off using localStorage instead - make it easy to convert
|
||||
window.convertCookieToLocalStorage = function(name) {
|
||||
var cookie=readCookie(name);
|
||||
if(cookie !== undefined) {
|
||||
console.log('converting cookie '+name+' to localStorage');
|
||||
if(localStorage[name] === undefined) {
|
||||
localStorage[name] = cookie;
|
||||
}
|
||||
eraseCookie(name);
|
||||
}
|
||||
}
|
||||
|
||||
// add thousand separators to given number.
|
||||
// http://stackoverflow.com/a/1990590/1684530 by Doug Neiner.
|
||||
window.digits = function(d) {
|
||||
return (d+"").replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1 ");
|
||||
}
|
||||
|
||||
|
||||
window.requestParameterMunges = [
|
||||
// now obsolete (they don't have some of the new parameters) munge sets deleted
|
||||
|
||||
|
||||
// set 3 - in the update of 2013-09-30 (addition of 'alerts' chat tab)
|
||||
{
|
||||
'dashboard.getGameScore': 'fhlzntzkl5v7hcfh', // GET_GAME_SCORE
|
||||
'dashboard.getPaginatedPlextsV2': 'wzuitnswoda7w028', // GET_PAGINATED_PLEXTS
|
||||
'dashboard.getThinnedEntitiesV4': 'scgrm4lf2371esgw', // GET_THINNED_ENTITIES
|
||||
'dashboard.getPlayersByGuids': '81l6usczczoi3lfi', // LOOKUP_PLAYERS
|
||||
'dashboard.redeemReward': '8kop2koeld9b4c26', // REDEEM_REWARD
|
||||
'dashboard.sendInviteEmail': 't0ccodsm1nuo5uso', // SEND_INVITE_EMAIL
|
||||
'dashboard.sendPlext': 'k04cfjwwsg3h3827', // SEND_PLEXT
|
||||
|
||||
method: '22ux2z96jwq5zn78',
|
||||
version: 'kf6hgl9yau03ws0o', //guessed parameter name - only seen munged
|
||||
version_parameter: '4608f4356a6f55690f127fb542f557f98de66169', // passed as the value to the above parameter
|
||||
boundsParamsList: '29t16cmsn6l3r2xg',
|
||||
id: '7rogqhp5pzcqobcw',
|
||||
minLatE6: 'yzbnp7z9bd28p0yr',
|
||||
minLngE6: '2pdhntvo85cd90bw',
|
||||
maxLatE6: 'c4ivr013h4dr68pd',
|
||||
maxLngE6: '4p8oorcrwalc1mzf',
|
||||
timestampMs: 'vd2rsa9v6f8q606s',
|
||||
qk: 'cblh9xe0bgwjy5ij',
|
||||
desiredNumItems: '3ymaq7slb165porj',
|
||||
minTimestampMs: 's9jf2seni33y3gyu',
|
||||
maxTimestampMs: '2kh3vti98rhp3g29',
|
||||
chatTab: '7n7ocqfq1p18352b', //guessed parameter name - only seen munged
|
||||
ascendingTimestampOrder: 'p88a2ztchtjhiazl',
|
||||
message: 'e8qm0kptw2trrcrw',
|
||||
latE6: 'fja1phtsqxm71dqm',
|
||||
lngE6: 'iut1tb7c0x726hwn',
|
||||
guids: '5hyiwhwc0jyljvro',
|
||||
inviteeEmailAddress: 's9z6zt03eymzxhkj',
|
||||
},
|
||||
|
||||
// set 4 - second update of 2013-09-30
|
||||
{
|
||||
'dashboard.getGameScore': 'ija9jgrf5hj7wm9r', // GET_GAME_SCORE
|
||||
'dashboard.getPaginatedPlextsV2': '0elftx739mkbzi1b', // GET_PAGINATED_PLEXTS
|
||||
'dashboard.getThinnedEntitiesV4': 'prv0ez8cbsykh63g', // GET_THINNED_ENTITIES
|
||||
'dashboard.getPlayersByGuids': 'i0lxy6nc695z9ka3', // LOOKUP_PLAYERS
|
||||
'dashboard.redeemReward': '376oivna8rf8qbfj', // REDEEM_REWARD
|
||||
'dashboard.sendInviteEmail': '96y930v5q96nrcrw', // SEND_INVITE_EMAIL
|
||||
'dashboard.sendPlext': 'c04kceytofuqvyqg', // SEND_PLEXT
|
||||
|
||||
method: '9we4b31i48ui4sdm',
|
||||
version: 'q402kn5zqisuo1ym', //guessed parameter name - only seen munged
|
||||
version_parameter: 'dbad4485024d446ae946e3d287b5d640029ef3e3', // passed as the value to the above parameter
|
||||
boundsParamsList: '3r5ctyvc2f653zjd',
|
||||
id: 'izey8ciqg2dz2oqc',
|
||||
minLatE6: 'cein0n4jrifa7ui2',
|
||||
minLngE6: 'lbd1juids3johtdo',
|
||||
maxLatE6: 'h4kyot9kmvd3g284',
|
||||
maxLngE6: 'sbci6jjc2d5g9uy4',
|
||||
timestampMs: '2wurn9giagbvv6bt',
|
||||
qk: 'hq73mwpjqyvcp6ul',
|
||||
desiredNumItems: 'kyo6vh5n58hmrnua',
|
||||
minTimestampMs: 'hu4swdftcp7mvkdi',
|
||||
maxTimestampMs: 'ly6ylae5lv1z9072',
|
||||
chatTab: 'q5kxut5rmbtlqbf9', //guessed parameter name - only seen munged
|
||||
ascendingTimestampOrder: 'hvfd0io35rahwjgr',
|
||||
message: 'z4hf7tzl27o14455',
|
||||
latE6: 'zyzh3bdxyd47vk1x',
|
||||
lngE6: 'n5d1f8pql51t641x',
|
||||
guids: 'gl16ehqoc3i3oi07',
|
||||
inviteeEmailAddress: 'orc9ufg7rp7g1y9j',
|
||||
},
|
||||
|
||||
];
|
||||
window.activeRequestMungeSet = undefined;
|
||||
|
||||
// attempt to guess the munge set in use, by looking therough the functions of the stock intel page for one of the munged params
|
||||
window.detectActiveMungeSet = function() {
|
||||
if (window.requestParameterMunges.length == 1) {
|
||||
// no point in searching through the code when there's only one set in use
|
||||
window.activeRequestMungeSet = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// try and find the stock page functions
|
||||
// FIXME? revert to searching through all the code? is that practical?
|
||||
var stockFunc = nemesis.dashboard.network.DataFetcher.prototype.sendRequest_.toString()
|
||||
for (var i in window.requestParameterMunges) {
|
||||
if (stockFunc.indexOf (window.requestParameterMunges[i]['method']) >= 0) {
|
||||
console.log('IITC: found request munge set index '+i+' in stock intel function nemesis.dashboard.network.DataFetcher.prototype.sendRequest_');
|
||||
window.activeRequestMungeSet = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (window.activeRequestMungeSet===undefined) {
|
||||
console.error('IITC: failed to find request munge set - IITC will likely fail');
|
||||
window.activeRequestMungeSet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// niantic now add some munging to the request parameters. so far, only two sets of this munging have been seen
|
||||
window.requestDataMunge = function(data) {
|
||||
var activeMunge = window.requestParameterMunges[window.activeRequestMungeSet];
|
||||
|
||||
function munge(obj) {
|
||||
if (Object.prototype.toString.call(obj) === '[object Array]') {
|
||||
// an array - munge each element of it
|
||||
var newobj = [];
|
||||
for (var i in obj) {
|
||||
newobj[i] = munge(obj[i]);
|
||||
}
|
||||
return newobj;
|
||||
} else if (typeof obj === 'object') {
|
||||
// an object: munge each property name, and pass the value through the munge process
|
||||
var newobj = Object();
|
||||
for (var p in obj) {
|
||||
var m = activeMunge[p];
|
||||
if (m === undefined) {
|
||||
console.error('Error: failed to find munge for object property '+p);
|
||||
newobj[p] = obj[p];
|
||||
} else {
|
||||
// rename the property
|
||||
newobj[m] = munge(obj[p]);
|
||||
}
|
||||
}
|
||||
return newobj;
|
||||
} else {
|
||||
// neither an array or an object - so must be a simple value. return it unmodified
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
var newdata = munge(data);
|
||||
return newdata;
|
||||
}
|
||||
|
||||
// posts AJAX request to Ingress API.
|
||||
// action: last part of the actual URL, the rpc/dashboard. is
|
||||
// added automatically
|
||||
// data: JSON data to post. method will be derived automatically from
|
||||
// action, but may be overridden. Expects to be given Hash.
|
||||
// Strings are not supported.
|
||||
// success: method to call on success. See jQuery API docs for avail-
|
||||
// able arguments: http://api.jquery.com/jQuery.ajax/
|
||||
// error: see above. Additionally it is logged if the request failed.
|
||||
window.postAjax = function(action, data, success, error) {
|
||||
if (window.activeRequestMungeSet===undefined) {
|
||||
window.detectActiveMungeSet();
|
||||
}
|
||||
var activeMunge = window.requestParameterMunges[window.activeRequestMungeSet];
|
||||
|
||||
var methodName = 'dashboard.'+action;
|
||||
var versionStr = 'version_parameter';
|
||||
|
||||
// munging of the method name - seen in Set 2 (onwards?)
|
||||
methodName = activeMunge[methodName];
|
||||
// and of the 'version' parameter
|
||||
versionStr = activeMunge[versionStr];
|
||||
|
||||
var post_data = JSON.stringify(window.requestDataMunge($.extend({method: methodName, version: versionStr}, data)));
|
||||
var remove = function(data, textStatus, jqXHR) { window.requests.remove(jqXHR); };
|
||||
var errCnt = function(jqXHR) { window.failedRequestCount++; window.requests.remove(jqXHR); };
|
||||
var result = $.ajax({
|
||||
url: '/r/'+methodName,
|
||||
type: 'POST',
|
||||
data: post_data,
|
||||
context: data,
|
||||
dataType: 'json',
|
||||
success: [remove, success],
|
||||
error: error ? [errCnt, error] : errCnt,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
beforeSend: function(req) {
|
||||
req.setRequestHeader('X-CSRFToken', readCookie('csrftoken'));
|
||||
}
|
||||
});
|
||||
result.action = action;
|
||||
return result;
|
||||
}
|
||||
|
||||
window.zeroPad = function(number,pad) {
|
||||
number = number.toString();
|
||||
var zeros = pad - number.length;
|
||||
return Array(zeros>0?zeros+1:0).join("0") + number;
|
||||
}
|
||||
|
||||
|
||||
// converts javascript timestamps to HH:mm:ss format if it was today;
|
||||
// otherwise it returns YYYY-MM-DD
|
||||
window.unixTimeToString = function(time, full) {
|
||||
if(!time) return null;
|
||||
var d = new Date(typeof time === 'string' ? parseInt(time) : time);
|
||||
var time = d.toLocaleTimeString();
|
||||
var date = d.getFullYear()+'-'+zeroPad(d.getMonth()+1,2)+'-'+zeroPad(d.getDate(),2);
|
||||
if(typeof full !== 'undefined' && full) return date + ' ' + time;
|
||||
if(d.toDateString() == new Date().toDateString())
|
||||
return time;
|
||||
else
|
||||
return date;
|
||||
}
|
||||
|
||||
// converts a javascript time to a precise date and time (optionally with millisecond precision)
|
||||
// formatted in ISO-style YYYY-MM-DD hh:mm:ss.mmm - but using local timezone
|
||||
window.unixTimeToDateTimeString = function(time, millisecond) {
|
||||
if(!time) return null;
|
||||
var d = new Date(typeof time === 'string' ? parseInt(time) : time);
|
||||
return d.getFullYear()+'-'+zeroPad(d.getMonth()+1,2)+'-'+zeroPad(d.getDate(),2)
|
||||
+' '+d.toLocaleTimeString()+(millisecond?'.'+zeroPad(d.getMilliseconds(),3):'');
|
||||
}
|
||||
|
||||
window.unixTimeToHHmm = function(time) {
|
||||
if(!time) return null;
|
||||
var d = new Date(typeof time === 'string' ? parseInt(time) : time);
|
||||
var h = '' + d.getHours(); h = h.length === 1 ? '0' + h : h;
|
||||
var s = '' + d.getMinutes(); s = s.length === 1 ? '0' + s : s;
|
||||
return h + ':' + s;
|
||||
}
|
||||
|
||||
window.formatInterval = function(seconds) {
|
||||
|
||||
var h = Math.floor(seconds / 3600);
|
||||
var m = Math.floor((seconds % 3600) / 60);
|
||||
var s = seconds % 60;
|
||||
|
||||
var text = '';
|
||||
if (h > 0) text += h+'h';
|
||||
if (m > 0) text += m+'m';
|
||||
if (s > 0 || text == '') text += s+'s';
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
window.rangeLinkClick = function() {
|
||||
if(window.portalRangeIndicator)
|
||||
window.map.fitBounds(window.portalRangeIndicator.getBounds());
|
||||
if(window.isSmartphone())
|
||||
window.smartphone.mapButton.click();
|
||||
}
|
||||
|
||||
window.showPortalPosLinks = function(lat, lng, name) {
|
||||
var encoded_name = 'undefined';
|
||||
if(name !== undefined) {
|
||||
encoded_name = encodeURIComponent(name);
|
||||
}
|
||||
|
||||
if (typeof android !== 'undefined' && android && android.intentPosLink) {
|
||||
android.intentPosLink(lat, lng, map.getZoom(), name, true);
|
||||
} else {
|
||||
var qrcode = '<div id="qrcode"></div>';
|
||||
var script = '<script>$(\'#qrcode\').qrcode({text:\'GEO:'+lat+','+lng+'\'});</script>';
|
||||
var gmaps = '<a href="https://maps.google.com/?q='+lat+','+lng+'%20('+encoded_name+')">Google Maps</a>';
|
||||
var bingmaps = '<a href="http://www.bing.com/maps/?v=2&cp='+lat+'~'+lng+'&lvl=16&sp=Point.'+lat+'_'+lng+'_'+encoded_name+'___">Bing Maps</a>';
|
||||
var osm = '<a href="http://www.openstreetmap.org/?mlat='+lat+'&mlon='+lng+'&zoom=16">OpenStreetMap</a>';
|
||||
var latLng = '<span><' + lat + ',' + lng +'></span>';
|
||||
dialog({
|
||||
html: '<div style="text-align: center;">' + qrcode + script + gmaps + '; ' + bingmaps + '; ' + osm + '<br />' + latLng + '</div>',
|
||||
title: name,
|
||||
id: 'poslinks'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.androidCopy = function(text) {
|
||||
if(typeof android === 'undefined' || !android || !android.copy)
|
||||
return true; // i.e. execute other actions
|
||||
else
|
||||
android.copy(text);
|
||||
return false;
|
||||
}
|
||||
|
||||
window.androidPermalink = function() {
|
||||
if(typeof android === 'undefined' || !android || !android.copy)
|
||||
return true; // i.e. execute other actions
|
||||
|
||||
var center = map.getCenter();
|
||||
android.intentPosLink(center.lat, center.lng, map.getZoom(), "Intel Map", false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
window.getPortalDataZoom = function() {
|
||||
var mapZoom = map.getZoom();
|
||||
|
||||
// make sure we're dealing with an integer here
|
||||
// (mobile: a float somehow gets through in some cases!)
|
||||
var z = parseInt(mapZoom);
|
||||
|
||||
// limiting the mazimum zoom level for data retrieval reduces the number of requests at high zoom levels
|
||||
// (as all portal data is retrieved at z=17, why retrieve multiple z=18 tiles when fewer z=17 would do?)
|
||||
// very effective along with the new cache code
|
||||
if (z > 17) z=17;
|
||||
|
||||
//sanity check - should never happen
|
||||
if (z < 0) z=0;
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
window.getMinPortalLevelForZoom = function(z) {
|
||||
//based on code from stock gen_dashboard.js
|
||||
switch(z) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return 8;
|
||||
case 4:
|
||||
case 5:
|
||||
return 7;
|
||||
case 6:
|
||||
case 7:
|
||||
return 6;
|
||||
case 8:
|
||||
return 5;
|
||||
case 9:
|
||||
case 10:
|
||||
return 4;
|
||||
case 11:
|
||||
case 12:
|
||||
return 3;
|
||||
case 13:
|
||||
case 14:
|
||||
return 2;
|
||||
case 15:
|
||||
case 16:
|
||||
return 1;
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
window.getMinPortalLevel = function() {
|
||||
var z = getPortalDataZoom();
|
||||
return getMinPortalLevelForZoom(z);
|
||||
}
|
||||
|
||||
// returns number of pixels left to scroll down before reaching the
|
||||
// bottom. Works similar to the native scrollTop function.
|
||||
window.scrollBottom = function(elm) {
|
||||
if(typeof elm === 'string') elm = $(elm);
|
||||
return elm.get(0).scrollHeight - elm.innerHeight() - elm.scrollTop();
|
||||
}
|
||||
|
||||
window.zoomToAndShowPortal = function(guid, latlng) {
|
||||
map.setView(latlng, 17);
|
||||
// if the data is available, render it immediately. Otherwise defer
|
||||
// until it becomes available.
|
||||
if(window.portals[guid])
|
||||
renderPortalDetails(guid);
|
||||
else
|
||||
urlPortal = guid;
|
||||
}
|
||||
|
||||
|
||||
String.prototype.capitalize = function() {
|
||||
return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/a/646643/1684530 by Bergi and CMS
|
||||
if (typeof String.prototype.startsWith !== 'function') {
|
||||
String.prototype.startsWith = function (str){
|
||||
return this.slice(0, str.length) === str;
|
||||
};
|
||||
}
|
||||
|
||||
// escape a javascript string, so quotes and backslashes are escaped with a backslash
|
||||
// (for strings passed as parameters to html onclick="..." for example)
|
||||
window.escapeJavascriptString = function(str) {
|
||||
return (str+'').replace(/[\\"']/g,'\\$&');
|
||||
}
|
||||
|
||||
//escape special characters, such as tags
|
||||
window.escapeHtmlSpecialChars = function(str) {
|
||||
var div = document.createElement(div);
|
||||
var text = document.createTextNode(str);
|
||||
div.appendChild(text);
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
window.prettyEnergy = function(nrg) {
|
||||
return nrg> 1000 ? Math.round(nrg/1000) + ' k': nrg;
|
||||
}
|
||||
|
||||
window.setPermaLink = function(elm) {
|
||||
var c = map.getCenter();
|
||||
var lat = Math.round(c.lat*1E6)/1E6;
|
||||
var lng = Math.round(c.lng*1E6)/1E6;
|
||||
var qry = 'll='+lat+','+lng+'&z=' + map.getZoom();
|
||||
$(elm).attr('href', '/intel?' + qry);
|
||||
}
|
||||
|
||||
window.uniqueArray = function(arr) {
|
||||
return $.grep(arr, function(v, i) {
|
||||
return $.inArray(v, arr) === i;
|
||||
});
|
||||
}
|
||||
|
||||
window.genFourColumnTable = function(blocks) {
|
||||
var t = $.map(blocks, function(detail, index) {
|
||||
if(!detail) return '';
|
||||
if(index % 2 === 0)
|
||||
return '<tr><td>'+detail[1]+'</td><th>'+detail[0]+'</th>';
|
||||
else
|
||||
return ' <th>'+detail[0]+'</th><td>'+detail[1]+'</td></tr>';
|
||||
}).join('');
|
||||
if(t.length % 2 === 1) t + '<td></td><td></td></tr>';
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
// converts given text with newlines (\n) and tabs (\t) to a HTML
|
||||
// table automatically.
|
||||
window.convertTextToTableMagic = function(text) {
|
||||
// check if it should be converted to a table
|
||||
if(!text.match(/\t/)) return text.replace(/\n/g, '<br>');
|
||||
|
||||
var data = [];
|
||||
var columnCount = 0;
|
||||
|
||||
// parse data
|
||||
var rows = text.split('\n');
|
||||
$.each(rows, function(i, row) {
|
||||
data[i] = row.split('\t');
|
||||
if(data[i].length > columnCount) columnCount = data[i].length;
|
||||
});
|
||||
|
||||
// build the table
|
||||
var table = '<table>';
|
||||
$.each(data, function(i, row) {
|
||||
table += '<tr>';
|
||||
$.each(data[i], function(k, cell) {
|
||||
var attributes = '';
|
||||
if(k === 0 && data[i].length < columnCount) {
|
||||
attributes = ' colspan="'+(columnCount - data[i].length + 1)+'"';
|
||||
}
|
||||
table += '<td'+attributes+'>'+cell+'</td>';
|
||||
});
|
||||
table += '</tr>';
|
||||
});
|
||||
table += '</table>';
|
||||
return table;
|
||||
}
|
||||
|
||||
// Given 3 sets of points in an array[3]{lat, lng} returns the area of the triangle
|
||||
window.calcTriArea = function(p) {
|
||||
return Math.abs((p[0].lat*(p[1].lng-p[2].lng)+p[1].lat*(p[2].lng-p[0].lng)+p[2].lat*(p[0].lng-p[1].lng))/2);
|
||||
}
|
||||
|
||||
// Update layerGroups display status to window.overlayStatus and localStorage 'ingress.intelmap.layergroupdisplayed'
|
||||
window.updateDisplayedLayerGroup = function(name, display) {
|
||||
overlayStatus[name] = display;
|
||||
localStorage['ingress.intelmap.layergroupdisplayed'] = JSON.stringify(overlayStatus);
|
||||
}
|
||||
|
||||
// Read layerGroup status from window.overlayStatus if it was added to map,
|
||||
// read from cookie if it has not added to map yet.
|
||||
// return 'defaultDisplay' if both overlayStatus and cookie didn't have the record
|
||||
window.isLayerGroupDisplayed = function(name, defaultDisplay) {
|
||||
if(typeof(overlayStatus[name]) !== 'undefined') return overlayStatus[name];
|
||||
|
||||
convertCookieToLocalStorage('ingress.intelmap.layergroupdisplayed');
|
||||
var layersJSON = localStorage['ingress.intelmap.layergroupdisplayed'];
|
||||
if(!layersJSON) return defaultDisplay;
|
||||
|
||||
var layers = JSON.parse(layersJSON);
|
||||
// keep latest overlayStatus
|
||||
overlayStatus = $.extend(layers, overlayStatus);
|
||||
if(typeof(overlayStatus[name]) === 'undefined') return defaultDisplay;
|
||||
return overlayStatus[name];
|
||||
}
|
||||
|
||||
window.addLayerGroup = function(name, layerGroup, defaultDisplay) {
|
||||
if(isLayerGroupDisplayed(name, defaultDisplay)) map.addLayer(layerGroup);
|
||||
layerChooser.addOverlay(layerGroup, name);
|
||||
}
|
||||
|
||||
window.clampLat = function(lat) {
|
||||
// the map projection used does not handle above approx +- 85 degrees north/south of the equator
|
||||
if (lat > 85.051128)
|
||||
lat = 85.051128;
|
||||
else if (lat < -85.051128)
|
||||
lat = -85.051128;
|
||||
return lat;
|
||||
}
|
||||
|
||||
window.clampLng = function(lng) {
|
||||
if (lng > 179.999999)
|
||||
lng = 179.999999;
|
||||
else if (lng < -180.0)
|
||||
lng = -180.0;
|
||||
return lng;
|
||||
}
|
||||
|
||||
|
||||
window.clampLatLng = function(latlng) {
|
||||
return new L.LatLng ( clampLat(latlng.lat), clampLng(latlng.lng) );
|
||||
}
|
||||
|
||||
window.clampLatLngBounds = function(bounds) {
|
||||
return new L.LatLngBounds ( clampLatLng(bounds.getSouthWest()), clampLatLng(bounds.getNorthEast()) );
|
||||
}
|
336
external/KML.js
vendored
Executable file
336
external/KML.js
vendored
Executable file
@ -0,0 +1,336 @@
|
||||
/*global L: true */
|
||||
|
||||
L.KML = L.FeatureGroup.extend({
|
||||
options: {
|
||||
async: true
|
||||
},
|
||||
|
||||
initialize: function(kml, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
this._kml = kml;
|
||||
this._layers = {};
|
||||
|
||||
if (kml) {
|
||||
this.addKML(kml, options, this.options.async);
|
||||
}
|
||||
},
|
||||
|
||||
loadXML: function(url, cb, options, async) {
|
||||
if (async == undefined) async = this.options.async;
|
||||
if (options == undefined) options = this.options;
|
||||
|
||||
var req = new window.XMLHttpRequest();
|
||||
req.open('GET', url, async);
|
||||
try {
|
||||
req.overrideMimeType('text/xml'); // unsupported by IE
|
||||
} catch(e) {}
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState != 4) return;
|
||||
if(req.status == 200) cb(req.responseXML, options);
|
||||
};
|
||||
req.send(null);
|
||||
},
|
||||
|
||||
addKML: function(url, options, async) {
|
||||
var _this = this;
|
||||
var cb = function(gpx, options) { _this._addKML(gpx, options) };
|
||||
this.loadXML(url, cb, options, async);
|
||||
},
|
||||
|
||||
_addKML: function(xml, options) {
|
||||
var layers = L.KML.parseKML(xml);
|
||||
if (!layers || !layers.length) return;
|
||||
for (var i = 0; i < layers.length; i++)
|
||||
{
|
||||
this.fire('addlayer', {
|
||||
layer: layers[i]
|
||||
});
|
||||
this.addLayer(layers[i]);
|
||||
}
|
||||
this.latLngs = L.KML.getLatLngs(xml);
|
||||
this.fire("loaded");
|
||||
},
|
||||
|
||||
latLngs: []
|
||||
});
|
||||
|
||||
L.Util.extend(L.KML, {
|
||||
|
||||
parseKML: function (xml) {
|
||||
var style = this.parseStyle(xml);
|
||||
var el = xml.getElementsByTagName("Folder");
|
||||
var layers = [], l;
|
||||
for (var i = 0; i < el.length; i++) {
|
||||
if (!this._check_folder(el[i])) { continue; }
|
||||
l = this.parseFolder(el[i], style);
|
||||
if (l) { layers.push(l); }
|
||||
}
|
||||
el = xml.getElementsByTagName('Placemark');
|
||||
for (var j = 0; j < el.length; j++) {
|
||||
if (!this._check_folder(el[j])) { continue; }
|
||||
l = this.parsePlacemark(el[j], xml, style);
|
||||
if (l) { layers.push(l); }
|
||||
}
|
||||
return layers;
|
||||
},
|
||||
|
||||
// Return false if e's first parent Folder is not [folder]
|
||||
// - returns true if no parent Folders
|
||||
_check_folder: function (e, folder) {
|
||||
e = e.parentElement;
|
||||
while (e && e.tagName !== "Folder")
|
||||
{
|
||||
e = e.parentElement;
|
||||
}
|
||||
return !e || e === folder;
|
||||
},
|
||||
|
||||
parseStyle: function (xml) {
|
||||
var style = {};
|
||||
var sl = xml.getElementsByTagName("Style");
|
||||
|
||||
//for (var i = 0; i < sl.length; i++) {
|
||||
var attributes = {color: true, width: true, Icon: true, href: true,
|
||||
hotSpot: true};
|
||||
|
||||
function _parse(xml) {
|
||||
var options = {};
|
||||
for (var i = 0; i < xml.childNodes.length; i++) {
|
||||
var e = xml.childNodes[i];
|
||||
var key = e.tagName;
|
||||
if (!attributes[key]) { continue; }
|
||||
if (key === 'hotSpot')
|
||||
{
|
||||
for (var j = 0; j < e.attributes.length; j++) {
|
||||
options[e.attributes[j].name] = e.attributes[j].nodeValue;
|
||||
}
|
||||
} else {
|
||||
var value = e.childNodes[0].nodeValue;
|
||||
if (key === 'color') {
|
||||
options.opacity = parseInt(value.substring(0, 2), 16) / 255.0;
|
||||
options.color = "#" + value.substring(6, 8) + value.substring(4, 6) + value.substring(2, 4);
|
||||
} else if (key === 'width') {
|
||||
options.weight = value;
|
||||
} else if (key === 'Icon') {
|
||||
ioptions = _parse(e);
|
||||
if (ioptions.href) { options.href = ioptions.href; }
|
||||
} else if (key === 'href') {
|
||||
options.href = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
for (var i = 0; i < sl.length; i++) {
|
||||
var e = sl[i], el;
|
||||
var options = {}, poptions = {}, ioptions = {};
|
||||
el = e.getElementsByTagName("LineStyle");
|
||||
if (el && el[0]) { options = _parse(el[0]); }
|
||||
el = e.getElementsByTagName("PolyStyle");
|
||||
if (el && el[0]) { poptions = _parse(el[0]); }
|
||||
if (poptions.color) { options.fillColor = poptions.color; }
|
||||
if (poptions.opacity) { options.fillOpacity = poptions.opacity; }
|
||||
el = e.getElementsByTagName("IconStyle");
|
||||
if (el && el[0]) { ioptions = _parse(el[0]); }
|
||||
if (ioptions.href) {
|
||||
// save anchor info until the image is loaded
|
||||
options.icon = new L.KMLIcon({
|
||||
iconUrl: ioptions.href,
|
||||
shadowUrl: null,
|
||||
iconAnchorRef: {x: ioptions.x, y: ioptions.y},
|
||||
iconAnchorType: {x: ioptions.xunits, y: ioptions.yunits}
|
||||
});
|
||||
}
|
||||
style['#' + e.getAttribute('id')] = options;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
|
||||
parseFolder: function (xml, style) {
|
||||
var el, layers = [], l;
|
||||
el = xml.getElementsByTagName('Folder');
|
||||
for (var i = 0; i < el.length; i++) {
|
||||
if (!this._check_folder(el[i], xml)) { continue; }
|
||||
l = this.parseFolder(el[i], style);
|
||||
if (l) { layers.push(l); }
|
||||
}
|
||||
el = xml.getElementsByTagName('Placemark');
|
||||
for (var j = 0; j < el.length; j++) {
|
||||
if (!this._check_folder(el[j], xml)) { continue; }
|
||||
l = this.parsePlacemark(el[j], xml, style);
|
||||
if (l) { layers.push(l); }
|
||||
}
|
||||
if (!layers.length) { return; }
|
||||
if (layers.length === 1) { return layers[0]; }
|
||||
return new L.FeatureGroup(layers);
|
||||
},
|
||||
|
||||
parsePlacemark: function (place, xml, style) {
|
||||
var i, j, el, options = {};
|
||||
el = place.getElementsByTagName('styleUrl');
|
||||
for (i = 0; i < el.length; i++) {
|
||||
var url = el[i].childNodes[0].nodeValue;
|
||||
for (var a in style[url])
|
||||
{
|
||||
// for jshint
|
||||
if (true)
|
||||
{
|
||||
options[a] = style[url][a];
|
||||
}
|
||||
}
|
||||
}
|
||||
var layers = [];
|
||||
|
||||
var parse = ['LineString', 'Polygon', 'Point'];
|
||||
for (j in parse) {
|
||||
// for jshint
|
||||
if (true)
|
||||
{
|
||||
var tag = parse[j];
|
||||
el = place.getElementsByTagName(tag);
|
||||
for (i = 0; i < el.length; i++) {
|
||||
var l = this["parse" + tag](el[i], xml, options);
|
||||
if (l) { layers.push(l); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!layers.length) {
|
||||
return;
|
||||
}
|
||||
var layer = layers[0];
|
||||
if (layers.length > 1) {
|
||||
layer = new L.FeatureGroup(layers);
|
||||
}
|
||||
|
||||
var name, descr = "";
|
||||
el = place.getElementsByTagName('name');
|
||||
if (el.length) {
|
||||
name = el[0].childNodes[0].nodeValue;
|
||||
}
|
||||
el = place.getElementsByTagName('description');
|
||||
for (i = 0; i < el.length; i++) {
|
||||
for (j = 0; j < el[i].childNodes.length; j++) {
|
||||
descr = descr + el[i].childNodes[j].nodeValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (name) {
|
||||
layer.bindPopup("<h2>" + name + "</h2>" + descr);
|
||||
}
|
||||
|
||||
return layer;
|
||||
},
|
||||
|
||||
parseCoords: function (xml) {
|
||||
var el = xml.getElementsByTagName('coordinates');
|
||||
return this._read_coords(el[0]);
|
||||
},
|
||||
|
||||
parseLineString: function (line, xml, options) {
|
||||
var coords = this.parseCoords(line);
|
||||
if (!coords.length) { return; }
|
||||
return new L.Polyline(coords, options);
|
||||
},
|
||||
|
||||
parsePoint: function (line, xml, options) {
|
||||
var el = line.getElementsByTagName('coordinates');
|
||||
if (!el.length) {
|
||||
return;
|
||||
}
|
||||
var ll = el[0].childNodes[0].nodeValue.split(',');
|
||||
return new L.KMLMarker(new L.LatLng(ll[1], ll[0]), options);
|
||||
},
|
||||
|
||||
parsePolygon: function (line, xml, options) {
|
||||
var el, polys = [], inner = [], i, coords;
|
||||
el = line.getElementsByTagName('outerBoundaryIs');
|
||||
for (i = 0; i < el.length; i++) {
|
||||
coords = this.parseCoords(el[i]);
|
||||
if (coords) {
|
||||
polys.push(coords);
|
||||
}
|
||||
}
|
||||
el = line.getElementsByTagName('innerBoundaryIs');
|
||||
for (i = 0; i < el.length; i++) {
|
||||
coords = this.parseCoords(el[i]);
|
||||
if (coords) {
|
||||
inner.push(coords);
|
||||
}
|
||||
}
|
||||
if (!polys.length) {
|
||||
return;
|
||||
}
|
||||
if (options.fillColor) {
|
||||
options.fill = true;
|
||||
}
|
||||
if (polys.length === 1) {
|
||||
return new L.Polygon(polys.concat(inner), options);
|
||||
}
|
||||
return new L.MultiPolygon(polys, options);
|
||||
},
|
||||
|
||||
getLatLngs: function (xml) {
|
||||
var el = xml.getElementsByTagName('coordinates');
|
||||
var coords = [];
|
||||
for (var j = 0; j < el.length; j++) {
|
||||
// text might span many childnodes
|
||||
coords = coords.concat(this._read_coords(el[j]));
|
||||
}
|
||||
return coords;
|
||||
},
|
||||
|
||||
_read_coords: function (el) {
|
||||
var text = "", coords = [], i;
|
||||
for (i = 0; i < el.childNodes.length; i++) {
|
||||
text = text + el.childNodes[i].nodeValue;
|
||||
}
|
||||
text = text.split(/[\s\n]+/);
|
||||
for (i = 0; i < text.length; i++) {
|
||||
var ll = text[i].split(',');
|
||||
if (ll.length < 2) {
|
||||
continue;
|
||||
}
|
||||
coords.push(new L.LatLng(ll[1], ll[0]));
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
L.KMLIcon = L.Icon.extend({
|
||||
|
||||
createIcon: function () {
|
||||
var img = this._createIcon('icon');
|
||||
img.onload = function () {
|
||||
var i = new Image();
|
||||
i.src = this.src;
|
||||
this.style.width = i.width + 'px';
|
||||
this.style.height = i.height + 'px';
|
||||
|
||||
if (this.anchorType.x === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') {
|
||||
img.style.marginLeft = (-this.anchor.x * i.width) + 'px';
|
||||
}
|
||||
if (this.anchorType.y === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') {
|
||||
img.style.marginTop = (-(1 - this.anchor.y) * i.height) + 'px';
|
||||
}
|
||||
this.style.display = "";
|
||||
};
|
||||
return img;
|
||||
},
|
||||
|
||||
_setIconStyles: function (img, name) {
|
||||
L.Icon.prototype._setIconStyles.apply(this, [img, name])
|
||||
// save anchor information to the image
|
||||
img.anchor = this.options.iconAnchorRef;
|
||||
img.anchorType = this.options.iconAnchorType;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
L.KMLMarker = L.Marker.extend({
|
||||
options: {
|
||||
icon: new L.KMLIcon.Default()
|
||||
}
|
||||
});
|
16
external/L.Geodesic.js
vendored
16
external/L.Geodesic.js
vendored
@ -44,7 +44,7 @@ Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw
|
||||
lat1, lat2, lng1, lng2, dLng, d, segments,
|
||||
f, A, B, x, y, z, fLat, fLng;
|
||||
|
||||
dLng = Math.abs(endLatlng.lng - startLatlng.lng) * d2r;
|
||||
dLng = (endLatlng.lng - startLatlng.lng) * d2r;
|
||||
lat1 = startLatlng.lat * d2r;
|
||||
lat2 = endLatlng.lat * d2r;
|
||||
lng1 = startLatlng.lng * d2r;
|
||||
@ -60,14 +60,15 @@ Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw
|
||||
// rounding errors? maths bug? not sure - but it solves the issue! and is a slight optimisation)
|
||||
for (i = 1; i < segments; i++) {
|
||||
// http://williams.best.vwh.net/avform.htm#Intermediate
|
||||
// modified to handle longitude above +-180 degrees
|
||||
f = i / segments;
|
||||
A = Math.sin((1-f)*d) / Math.sin(d);
|
||||
B = Math.sin(f*d) / Math.sin(d);
|
||||
x = A * Math.cos(lat1) * Math.cos(lng1) + B * Math.cos(lat2) * Math.cos(lng2);
|
||||
y = A * Math.cos(lat1) * Math.sin(lng1) + B * Math.cos(lat2) * Math.sin(lng2);
|
||||
z = A * Math.sin(lat1) + B * Math.sin(lat2);
|
||||
x = A * Math.cos(lat1) * Math.cos(0) + B * Math.cos(lat2) * Math.cos(dLng);
|
||||
y = A * Math.cos(lat1) * Math.sin(0) + B * Math.cos(lat2) * Math.sin(dLng);
|
||||
z = A * Math.sin(lat1) + B * Math.sin(lat2);
|
||||
fLat = r2d * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
|
||||
fLng = r2d * Math.atan2(y, x);
|
||||
fLng = r2d * (Math.atan2(y, x)+lng1);
|
||||
|
||||
convertedPoints.push(L.latLng([fLat, fLng]));
|
||||
}
|
||||
@ -174,10 +175,9 @@ Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw
|
||||
|
||||
var calcLatLngAtAngle = function(angle) {
|
||||
var lat = Math.asin(sinCentreLat*cosRadRadius + cosCentreLat*sinRadRadius*Math.cos(angle));
|
||||
var lng = centreLng + Math.atan2(Math.sin(angle)*sinRadRadius*cosCentreLat, cosRadRadius-sinCentreLat*Math.sin(lat));
|
||||
|
||||
var lon = centreLng + Math.asin( Math.sin(angle) * sinRadRadius / cosCentreLat )
|
||||
|
||||
return L.latLng(lat * r2d,lon * r2d);
|
||||
return L.latLng(lat * r2d,lng * r2d);
|
||||
}
|
||||
|
||||
|
||||
|
54
external/leaflet.draw.js
vendored
54
external/leaflet.draw.js
vendored
@ -822,7 +822,7 @@ L.Draw.Circle = L.Draw.SimpleShape.extend({
|
||||
|
||||
_drawShape: function (latlng) {
|
||||
if (!this._shape) {
|
||||
this._shape = new L.Circle(this._startLatLng, this._startLatLng.distanceTo(latlng), this.options.shapeOptions);
|
||||
this._shape = new L.GeodesicCircle(this._startLatLng, this._startLatLng.distanceTo(latlng), this.options.shapeOptions);
|
||||
this._map.addLayer(this._shape);
|
||||
} else {
|
||||
this._shape.setRadius(this._startLatLng.distanceTo(latlng));
|
||||
@ -830,7 +830,7 @@ L.Draw.Circle = L.Draw.SimpleShape.extend({
|
||||
},
|
||||
|
||||
_fireCreatedEvent: function () {
|
||||
var circle = new L.Circle(this._startLatLng, this._shape.getRadius(), this.options.shapeOptions);
|
||||
var circle = new L.GeodesicCircle(this._startLatLng, this._shape.getRadius(), this.options.shapeOptions);
|
||||
L.Draw.SimpleShape.prototype._fireCreatedEvent.call(this, circle);
|
||||
},
|
||||
|
||||
@ -1502,10 +1502,8 @@ L.Edit.Circle = L.Edit.SimpleShape.extend({
|
||||
},
|
||||
|
||||
_getResizeMarkerPoint: function (latlng) {
|
||||
// From L.shape.getBounds()
|
||||
var delta = this._shape._radius * Math.cos(Math.PI / 4),
|
||||
point = this._map.project(latlng);
|
||||
return this._map.unproject([point.x + delta, point.y - delta]);
|
||||
var latRadius = (this._shape.getRadius() / 40075017) * 360;
|
||||
return L.latLng(latlng.lat+latRadius,latlng.lng);
|
||||
},
|
||||
|
||||
_move: function (latlng) {
|
||||
@ -1548,6 +1546,28 @@ L.Circle.addInitHook(function () {
|
||||
});
|
||||
});
|
||||
|
||||
L.GeodesicCircle.addInitHook(function () {
|
||||
if (L.Edit.Circle) {
|
||||
this.editing = new L.Edit.Circle(this);
|
||||
|
||||
if (this.options.editable) {
|
||||
this.editing.enable();
|
||||
}
|
||||
}
|
||||
|
||||
this.on('add', function () {
|
||||
if (this.editing && this.editing.enabled()) {
|
||||
this.editing.addHooks();
|
||||
}
|
||||
});
|
||||
|
||||
this.on('remove', function () {
|
||||
if (this.editing && this.editing.enabled()) {
|
||||
this.editing.removeHooks();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* L.LatLngUtil contains different utility functions for LatLngs.
|
||||
*/
|
||||
@ -2432,16 +2452,16 @@ L.EditToolbar.Edit = L.Handler.extend({
|
||||
var id = L.Util.stamp(layer);
|
||||
|
||||
if (!this._uneditedLayerProps[id]) {
|
||||
// Polyline, Polygon or Rectangle
|
||||
if (layer instanceof L.GeodesicPolyline || layer instanceof L.GeodesicPolygon || layer instanceof L.Rectangle) {
|
||||
this._uneditedLayerProps[id] = {
|
||||
latlngs: L.LatLngUtil.cloneLatLngs(layer.getLatLngs())
|
||||
};
|
||||
} else if (layer instanceof L.Circle) {
|
||||
if (layer instanceof L.GeodesicCircle || layer instanceof L.Circle) {
|
||||
this._uneditedLayerProps[id] = {
|
||||
latlng: L.LatLngUtil.cloneLatLng(layer.getLatLng()),
|
||||
radius: layer.getRadius()
|
||||
};
|
||||
} else if (layer instanceof L.GeodesicPolyline || layer instanceof L.GeodesicPolygon || layer instanceof L.Rectangle) {
|
||||
// Polyline, Polygon or Rectangle
|
||||
this._uneditedLayerProps[id] = {
|
||||
latlngs: L.LatLngUtil.cloneLatLngs(layer.getLatLngs())
|
||||
};
|
||||
} else { // Marker
|
||||
this._uneditedLayerProps[id] = {
|
||||
latlng: L.LatLngUtil.cloneLatLng(layer.getLatLng())
|
||||
@ -2454,12 +2474,12 @@ L.EditToolbar.Edit = L.Handler.extend({
|
||||
var id = L.Util.stamp(layer);
|
||||
layer.edited = false;
|
||||
if (this._uneditedLayerProps.hasOwnProperty(id)) {
|
||||
// Polyline, Polygon or Rectangle
|
||||
if (layer instanceof L.GeodesicPolyline || layer instanceof L.GeodesicPolygon || layer instanceof L.Rectangle) {
|
||||
layer.setLatLngs(this._uneditedLayerProps[id].latlngs);
|
||||
} else if (layer instanceof L.Circle) {
|
||||
if (layer instanceof L.GeodesicCircle || layer instanceof L.Circle) {
|
||||
layer.setLatLng(this._uneditedLayerProps[id].latlng);
|
||||
layer.setRadius(this._uneditedLayerProps[id].radius);
|
||||
} else if (layer instanceof L.GeodesicPolyline || layer instanceof L.GeodesicPolygon || layer instanceof L.Rectangle) {
|
||||
// Polyline, Polygon or Rectangle
|
||||
layer.setLatLngs(this._uneditedLayerProps[id].latlngs);
|
||||
} else { // Marker
|
||||
layer.setLatLng(this._uneditedLayerProps[id].latlng);
|
||||
}
|
||||
@ -2522,7 +2542,7 @@ L.EditToolbar.Edit = L.Handler.extend({
|
||||
layer.options.previousOptions = layer.options;
|
||||
|
||||
// Make sure that Polylines are not filled
|
||||
if (!(layer instanceof L.Circle) && !(layer instanceof L.GeodesicPolygon) && !(layer instanceof L.Rectangle)) {
|
||||
if (!(layer instanceof L.Circle) && !(layer instanceof L.GeodesicCircle) && !(layer instanceof L.GeodesicPolygon) && !(layer instanceof L.Rectangle)) {
|
||||
pathOptions.fill = false;
|
||||
}
|
||||
|
||||
|
168
external/leaflet.filelayer.js
vendored
Executable file
168
external/leaflet.filelayer.js
vendored
Executable file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Load files *locally* (GeoJSON, KML, GPX) into the map
|
||||
* using the HTML5 File API.
|
||||
*
|
||||
* Requires Pavel Shramov's GPX.js
|
||||
* https://github.com/shramov/leaflet-plugins/blob/d74d67/layer/vector/GPX.js
|
||||
*/
|
||||
var FileLoader = L.Class.extend({
|
||||
includes: L.Mixin.Events,
|
||||
options: {
|
||||
layerOptions: {}
|
||||
},
|
||||
|
||||
initialize: function (map, options) {
|
||||
this._map = map;
|
||||
L.Util.setOptions(this, options);
|
||||
|
||||
this._parsers = {
|
||||
'geojson': this._loadGeoJSON,
|
||||
'gpx': this._convertToGeoJSON,
|
||||
'kml': this._convertToGeoJSON
|
||||
};
|
||||
},
|
||||
|
||||
load: function (file /* File */) {
|
||||
// Check file extension
|
||||
var ext = file.name.split('.').pop(),
|
||||
parser = this._parsers[ext];
|
||||
if (!parser) {
|
||||
window.alert("Unsupported file type " + file.type + '(' + ext + ')');
|
||||
return;
|
||||
}
|
||||
// Read selected file using HTML5 File API
|
||||
var reader = new FileReader();
|
||||
reader.onload = L.Util.bind(function (e) {
|
||||
this.fire('data:loading', {filename: file.name, format: ext});
|
||||
var layer = parser.call(this, e.target.result, ext);
|
||||
this.fire('data:loaded', {layer: layer, filename: file.name, format: ext});
|
||||
}, this);
|
||||
reader.readAsText(file);
|
||||
},
|
||||
|
||||
_loadGeoJSON: function (content) {
|
||||
if (typeof content == 'string') {
|
||||
content = JSON.parse(content);
|
||||
}
|
||||
return L.geoJson(content, this.options.layerOptions).addTo(this._map);
|
||||
},
|
||||
|
||||
_convertToGeoJSON: function (content, format) {
|
||||
// Format is either 'gpx' or 'kml'
|
||||
if (typeof content == 'string') {
|
||||
content = ( new window.DOMParser() ).parseFromString(content, "text/xml");
|
||||
}
|
||||
var geojson = toGeoJSON[format](content);
|
||||
return this._loadGeoJSON(geojson);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
L.Control.FileLayerLoad = L.Control.extend({
|
||||
statics: {
|
||||
TITLE: 'Load local file (GPX, KML, GeoJSON)',
|
||||
LABEL: '⌅'
|
||||
},
|
||||
options: {
|
||||
position: 'topleft',
|
||||
fitBounds: true,
|
||||
layerOptions: {}
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
L.Util.setOptions(this, options);
|
||||
this.loader = null;
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
this.loader = new FileLoader(map, {layerOptions: this.options.layerOptions});
|
||||
|
||||
this.loader.on('data:loaded', function (e) {
|
||||
// Fit bounds after loading
|
||||
if (this.options.fitBounds) {
|
||||
window.setTimeout(function () {
|
||||
map.fitBounds(e.layer.getBounds()).zoomOut();
|
||||
}, 500);
|
||||
}
|
||||
}, this);
|
||||
|
||||
// Initialize Drag-and-drop
|
||||
this._initDragAndDrop(map);
|
||||
|
||||
// Initialize map control
|
||||
return this._initContainer();
|
||||
},
|
||||
|
||||
_initDragAndDrop: function (map) {
|
||||
var fileLoader = this.loader,
|
||||
dropbox = map._container;
|
||||
|
||||
var callbacks = {
|
||||
dragenter: function () {
|
||||
map.scrollWheelZoom.disable();
|
||||
},
|
||||
dragleave: function () {
|
||||
map.scrollWheelZoom.enable();
|
||||
},
|
||||
dragover: function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
},
|
||||
drop: function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
var files = Array.prototype.slice.apply(e.dataTransfer.files),
|
||||
i = files.length;
|
||||
setTimeout(function(){
|
||||
fileLoader.load(files.shift());
|
||||
if (files.length > 0) {
|
||||
setTimeout(arguments.callee, 25);
|
||||
}
|
||||
}, 25);
|
||||
map.scrollWheelZoom.enable();
|
||||
}
|
||||
};
|
||||
for (var name in callbacks)
|
||||
dropbox.addEventListener(name, callbacks[name], false);
|
||||
},
|
||||
|
||||
_initContainer: function () {
|
||||
// Create an invisible file input
|
||||
var fileInput = L.DomUtil.create('input', 'hidden', container);
|
||||
fileInput.type = 'file';
|
||||
fileInput.accept = '.gpx,.kml,.geojson';
|
||||
fileInput.style.display = 'none';
|
||||
// Load on file change
|
||||
var fileLoader = this.loader;
|
||||
fileInput.addEventListener("change", function (e) {
|
||||
fileLoader.load(this.files[0]);
|
||||
}, false);
|
||||
|
||||
// Create a button, and bind click on hidden file input
|
||||
var zoomName = 'leaflet-control-filelayer leaflet-control-zoom',
|
||||
barName = 'leaflet-bar',
|
||||
partName = barName + '-part',
|
||||
container = L.DomUtil.create('div', zoomName + ' ' + barName);
|
||||
var link = L.DomUtil.create('a', zoomName + '-in ' + partName, container);
|
||||
link.innerHTML = L.Control.FileLayerLoad.LABEL;
|
||||
link.href = '#';
|
||||
link.title = L.Control.FileLayerLoad.TITLE;
|
||||
|
||||
var stop = L.DomEvent.stopPropagation;
|
||||
L.DomEvent
|
||||
.on(link, 'click', stop)
|
||||
.on(link, 'mousedown', stop)
|
||||
.on(link, 'dblclick', stop)
|
||||
.on(link, 'click', L.DomEvent.preventDefault)
|
||||
.on(link, 'click', function (e) {
|
||||
fileInput.click();
|
||||
e.preventDefault();
|
||||
});
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
||||
L.Control.fileLayerLoad = function (options) {
|
||||
return new L.Control.FileLayerLoad(options);
|
||||
};
|
224
external/togeojson.js
vendored
Executable file
224
external/togeojson.js
vendored
Executable file
@ -0,0 +1,224 @@
|
||||
toGeoJSON = (function() {
|
||||
'use strict';
|
||||
|
||||
var removeSpace = (/\s*/g),
|
||||
trimSpace = (/^\s*|\s*$/g),
|
||||
splitSpace = (/\s+/);
|
||||
// generate a short, numeric hash of a string
|
||||
function okhash(x) {
|
||||
if (!x || !x.length) return 0;
|
||||
for (var i = 0, h = 0; i < x.length; i++) {
|
||||
h = ((h << 5) - h) + x.charCodeAt(i) | 0;
|
||||
} return h;
|
||||
}
|
||||
// all Y children of X
|
||||
function get(x, y) { return x.getElementsByTagName(y); }
|
||||
function attr(x, y) { return x.getAttribute(y); }
|
||||
function attrf(x, y) { return parseFloat(attr(x, y)); }
|
||||
// one Y child of X, if any, otherwise null
|
||||
function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
|
||||
function norm(el) { if (el.normalize) { el.normalize(); } return el; }
|
||||
// cast array x into numbers
|
||||
function numarray(x) {
|
||||
for (var j = 0, o = []; j < x.length; j++) o[j] = parseFloat(x[j]);
|
||||
return o;
|
||||
}
|
||||
function clean(x) {
|
||||
var o = {};
|
||||
for (var i in x) if (x[i]) o[i] = x[i];
|
||||
return o;
|
||||
}
|
||||
// get the content of a text node, if any
|
||||
function nodeVal(x) { if (x) {norm(x);} return x && x.firstChild && x.firstChild.nodeValue; }
|
||||
// get one coordinate from a coordinate array, if any
|
||||
function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
|
||||
// get all coordinates from a coordinate array as [[],[]]
|
||||
function coord(v) {
|
||||
var coords = v.replace(trimSpace, '').split(splitSpace),
|
||||
o = [];
|
||||
for (var i = 0; i < coords.length; i++) {
|
||||
o.push(coord1(coords[i]));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
function coordPair(x) { return [attrf(x, 'lon'), attrf(x, 'lat')]; }
|
||||
|
||||
// create a new feature collection parent object
|
||||
function fc() {
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
features: []
|
||||
};
|
||||
}
|
||||
|
||||
var serializer;
|
||||
if (typeof XMLSerializer !== 'undefined') {
|
||||
serializer = new XMLSerializer();
|
||||
} else if (typeof require !== 'undefined') {
|
||||
serializer = new (require('xmldom').XMLSerializer)();
|
||||
}
|
||||
function xml2str(str) { return serializer.serializeToString(str); }
|
||||
|
||||
var t = {
|
||||
kml: function(doc, o) {
|
||||
o = o || {};
|
||||
|
||||
var gj = fc(),
|
||||
// styleindex keeps track of hashed styles in order to match features
|
||||
styleIndex = {},
|
||||
// atomic geospatial types supported by KML - MultiGeometry is
|
||||
// handled separately
|
||||
geotypes = ['Polygon', 'LineString', 'Point', 'Track'],
|
||||
// all root placemarks in the file
|
||||
placemarks = get(doc, 'Placemark'),
|
||||
styles = get(doc, 'Style');
|
||||
|
||||
for (var k = 0; k < styles.length; k++) {
|
||||
styleIndex['#' + attr(styles[k], 'id')] = okhash(xml2str(styles[k])).toString(16);
|
||||
}
|
||||
for (var j = 0; j < placemarks.length; j++) {
|
||||
gj.features = gj.features.concat(getPlacemark(placemarks[j]));
|
||||
}
|
||||
function gxCoord(v) { return numarray(v.split(' ')); }
|
||||
function gxCoords(root) {
|
||||
var elems = get(root, 'coord', 'gx'), coords = [];
|
||||
for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
|
||||
return coords;
|
||||
}
|
||||
function getGeometry(root) {
|
||||
var geomNode, geomNodes, i, j, k, geoms = [];
|
||||
if (get1(root, 'MultiGeometry')) return getGeometry(get1(root, 'MultiGeometry'));
|
||||
if (get1(root, 'MultiTrack')) return getGeometry(get1(root, 'MultiTrack'));
|
||||
for (i = 0; i < geotypes.length; i++) {
|
||||
geomNodes = get(root, geotypes[i]);
|
||||
if (geomNodes) {
|
||||
for (j = 0; j < geomNodes.length; j++) {
|
||||
geomNode = geomNodes[j];
|
||||
if (geotypes[i] == 'Point') {
|
||||
geoms.push({
|
||||
type: 'Point',
|
||||
coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
|
||||
});
|
||||
} else if (geotypes[i] == 'LineString') {
|
||||
geoms.push({
|
||||
type: 'LineString',
|
||||
coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
|
||||
});
|
||||
} else if (geotypes[i] == 'Polygon') {
|
||||
var rings = get(geomNode, 'LinearRing'),
|
||||
coords = [];
|
||||
for (k = 0; k < rings.length; k++) {
|
||||
coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
|
||||
}
|
||||
geoms.push({
|
||||
type: 'Polygon',
|
||||
coordinates: coords
|
||||
});
|
||||
} else if (geotypes[i] == 'Track') {
|
||||
geoms.push({
|
||||
type: 'LineString',
|
||||
coordinates: gxCoords(geomNode)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return geoms;
|
||||
}
|
||||
function getPlacemark(root) {
|
||||
var geoms = getGeometry(root), i, properties = {},
|
||||
name = nodeVal(get1(root, 'name')),
|
||||
styleUrl = nodeVal(get1(root, 'styleUrl')),
|
||||
description = nodeVal(get1(root, 'description')),
|
||||
extendedData = get1(root, 'ExtendedData');
|
||||
|
||||
if (!geoms.length) return [];
|
||||
if (name) properties.name = name;
|
||||
if (styleUrl && styleIndex[styleUrl]) {
|
||||
properties.styleUrl = styleUrl;
|
||||
properties.styleHash = styleIndex[styleUrl];
|
||||
}
|
||||
if (description) properties.description = description;
|
||||
if (extendedData) {
|
||||
var datas = get(extendedData, 'Data'),
|
||||
simpleDatas = get(extendedData, 'SimpleData');
|
||||
|
||||
for (i = 0; i < datas.length; i++) {
|
||||
properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
|
||||
}
|
||||
for (i = 0; i < simpleDatas.length; i++) {
|
||||
properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
|
||||
}
|
||||
}
|
||||
return [{
|
||||
type: 'Feature',
|
||||
geometry: (geoms.length === 1) ? geoms[0] : {
|
||||
type: 'GeometryCollection',
|
||||
geometries: geoms
|
||||
},
|
||||
properties: properties
|
||||
}];
|
||||
}
|
||||
return gj;
|
||||
},
|
||||
gpx: function(doc, o) {
|
||||
var i,
|
||||
tracks = get(doc, 'trk'),
|
||||
routes = get(doc, 'rte'),
|
||||
waypoints = get(doc, 'wpt'),
|
||||
// a feature collection
|
||||
gj = fc();
|
||||
for (i = 0; i < tracks.length; i++) {
|
||||
gj.features.push(getLinestring(tracks[i], 'trkpt'));
|
||||
}
|
||||
for (i = 0; i < routes.length; i++) {
|
||||
gj.features.push(getLinestring(routes[i], 'rtept'));
|
||||
}
|
||||
for (i = 0; i < waypoints.length; i++) {
|
||||
gj.features.push(getPoint(waypoints[i]));
|
||||
}
|
||||
function getLinestring(node, pointname) {
|
||||
var j, pts = get(node, pointname), line = [];
|
||||
for (j = 0; j < pts.length; j++) {
|
||||
line.push(coordPair(pts[j]));
|
||||
}
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: getProperties(node),
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: line
|
||||
}
|
||||
};
|
||||
}
|
||||
function getPoint(node) {
|
||||
var prop = getProperties(node);
|
||||
prop.ele = nodeVal(get1(node, 'ele'));
|
||||
prop.sym = nodeVal(get1(node, 'sym'));
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: prop,
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: coordPair(node)
|
||||
}
|
||||
};
|
||||
}
|
||||
function getProperties(node) {
|
||||
var meta = ['name', 'desc', 'author', 'copyright', 'link',
|
||||
'time', 'keywords'],
|
||||
prop = {},
|
||||
k;
|
||||
for (k = 0; k < meta.length; k++) {
|
||||
prop[meta[k]] = nodeVal(get1(node, meta[k]));
|
||||
}
|
||||
return clean(prop);
|
||||
}
|
||||
return gj;
|
||||
}
|
||||
};
|
||||
return t;
|
||||
})();
|
||||
|
||||
if (typeof module !== 'undefined') module.exports = toGeoJSON;
|
BIN
images/marker-star.png
Normal file
BIN
images/marker-star.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 978 B |
BIN
images/open-folder-icon_sml.png
Normal file
BIN
images/open-folder-icon_sml.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 345 B |
22
main.js
22
main.js
@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @id ingress-intel-total-conversion@jonatkins
|
||||
// @name IITC: Ingress intel map total conversion
|
||||
// @version 0.14.2.@@DATETIMEVERSION@@
|
||||
// @version 0.14.5.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
@ -40,10 +40,10 @@ if(!d) {
|
||||
if(document.getElementById('header_email')) {
|
||||
// however, we are logged in.
|
||||
setTimeout('location.reload();', 3*1000);
|
||||
throw('Page doesn’t have player data, but you are logged in. Reloading in 3s.');
|
||||
throw("Page doesn't have player data, but you are logged in. Reloading in 3s.");
|
||||
}
|
||||
// FIXME: handle nia takedown in progress
|
||||
throw('Couldn’t retrieve player data. Are you logged in?');
|
||||
throw("Couldn't retrieve player data. Are you logged in?");
|
||||
}
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ document.getElementsByTagName('head')[0].innerHTML = ''
|
||||
+ '<style>@@INCLUDESTRING:style.css@@</style>'
|
||||
+ '<style>@@INCLUDESTRING:external/leaflet.css@@</style>'
|
||||
//note: smartphone.css injection moved into code/smartphone.js
|
||||
+ '<link href="http://fonts.googleapis.com/css?family=Roboto:normal,bold&subset=latin,cyrillic-ext,greek-ext,greek,cyrillic,latin-ext,vietnamese" rel="stylesheet" type="text/css">';
|
||||
+ '<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Roboto:100,100italic,300,300italic,400,400italic,500,500italic,700,700italic&subset=latin,cyrillic-ext,greek-ext,greek,vietnamese,latin-ext,cyrillic"/>';
|
||||
|
||||
document.getElementsByTagName('body')[0].innerHTML = ''
|
||||
+ '<div id="map">Loading, please wait</div>'
|
||||
@ -100,12 +100,18 @@ document.getElementsByTagName('body')[0].innerHTML = ''
|
||||
+ ' </div>'
|
||||
+ ' </div>'
|
||||
+ '</div>'
|
||||
+ '<div id="updatestatus"><div id="innerstatus"></div></div>';
|
||||
+ '<div id="updatestatus"><div id="innerstatus"></div></div>'
|
||||
// avoid error by stock JS
|
||||
+ '<div id="play_button"></div>';
|
||||
|
||||
// putting everything in a wrapper function that in turn is placed in a
|
||||
// script tag on the website allows us to execute in the site’s context
|
||||
// instead of in the Greasemonkey/Extension/etc. context.
|
||||
function wrapper() {
|
||||
function wrapper(info) {
|
||||
// a cut-down version of GM_info is passed as a parameter to the script
|
||||
// (not the full GM_info - it contains the ENTIRE script source!)
|
||||
window.script_info = info;
|
||||
|
||||
|
||||
// LEAFLET PREFER CANVAS ///////////////////////////////////////////////
|
||||
// Set to true if Leaflet should draw things using Canvas instead of SVG
|
||||
@ -238,5 +244,7 @@ if(typeof window.plugin !== 'function') window.plugin = function() {};
|
||||
|
||||
// inject code into site context
|
||||
var script = document.createElement('script');
|
||||
script.appendChild(document.createTextNode('('+ wrapper +')();'));
|
||||
var info = { buildName: '@@BUILDNAME@@', dateTimeVersion: '@@DATETIMEVERSION@@' };
|
||||
if (this.GM_info && this.GM_info.script) info.script = { version: GM_info.script.version, name: GM_info.script.name, description: GM_info.script.description };
|
||||
script.appendChild(document.createTextNode('('+ wrapper +')('+JSON.stringify(info)+');'));
|
||||
(document.body || document.head || document.documentElement).appendChild(script);
|
||||
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# reverse of mobile-test-setup - reverts the changes made to AndroidManifest.xml and any resource files
|
||||
|
||||
mv mobile/res/values/strings.xml~ mobile/res/values/strings.xml
|
||||
mv mobile/res/xml/preferences.xml~ mobile/res/xml/preferences.xml
|
||||
|
@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# quick-n-dirty script to rename the mobile build for tests
|
||||
|
||||
# rename the app title
|
||||
test -f mobile/res/values/strings.xml~ || cp mobile/res/values/strings.xml mobile/res/values/strings.xml~
|
||||
test -f mobile/res/xml/preferences.xml~ || cp mobile/res/xml/preferences.xml mobile/res/xml/preferences.xml~
|
||||
sed -e 's/IITC Mobile/IITCm Test/' mobile/res/values/strings.xml~ > mobile/res/values/strings.xml
|
||||
sed -e 's/targetPackage="com.cradle.iitc_mobile/targetPackage="com.cradle.iitc_mobile.test/' mobile/res/xml/preferences.xml~ > mobile/res/xml/preferences.xml
|
||||
|
||||
|
||||
# also, you'll need to build with
|
||||
# ant -Doverride.package.name=com.cradle.iitc_mobile.test ...
|
||||
# or similar
|
3
mobile/.gitignore
vendored
3
mobile/.gitignore
vendored
@ -18,6 +18,9 @@ bin/
|
||||
gen/
|
||||
out/
|
||||
|
||||
# private ant configs
|
||||
ant.properties
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
|
2
mobile/.idea/.name
generated
2
mobile/.idea/.name
generated
@ -1 +1 @@
|
||||
IITC-Mobile
|
||||
IITC_Mobile
|
9
mobile/.idea/libraries/android_support_v4.xml
generated
Normal file
9
mobile/.idea/libraries/android_support_v4.xml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="android-support-v4">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/libs/android-support-v4.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
23
mobile/.idea/misc.xml
generated
23
mobile/.idea/misc.xml
generated
@ -3,8 +3,31 @@
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="GradleLocalSettings">
|
||||
<option name="modificationStamps">
|
||||
<map>
|
||||
<entry key="$PROJECT_DIR$/../../ShowcaseView/library" value="1379967589662" />
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="Android 4.3 Platform" project-jdk-type="Android SDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
<state key="ProjectJDKs.UI">
|
||||
<settings>
|
||||
<last-edited>Android 4.3 Platform</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
|
2
mobile/.idea/modules.xml
generated
2
mobile/.idea/modules.xml
generated
@ -2,7 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/IITC-Mobile.iml" filepath="$PROJECT_DIR$/IITC-Mobile.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/IITC_Mobile.iml" filepath="$PROJECT_DIR$/IITC_Mobile.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
1
mobile/.idea/vcs.xml
generated
1
mobile/.idea/vcs.xml
generated
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="" />
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.cradle.iitc_mobile"
|
||||
android:versionCode="51"
|
||||
android:versionName="0.7.1">
|
||||
android:installLocation="auto"
|
||||
android:versionCode="58"
|
||||
android:versionName="0.8">
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
@ -13,8 +14,10 @@
|
||||
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<application
|
||||
android:name=".IITC_Application"
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_iitcm"
|
||||
android:label="@string/app_name"
|
||||
|
@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<notImportedProperties>
|
||||
<property>MANIFEST_FILE_PATH</property>
|
||||
<property>RESOURCES_DIR_PATH</property>
|
||||
<property>ASSETS_DIR_PATH</property>
|
||||
<property>NATIVE_LIBS_DIR_PATH</property>
|
||||
</notImportedProperties>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/libs/android-support-v4.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
|
@ -2,24 +2,18 @@
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<notImportedProperties>
|
||||
<property>MANIFEST_FILE_PATH</property>
|
||||
<property>RESOURCES_DIR_PATH</property>
|
||||
<property>ASSETS_DIR_PATH</property>
|
||||
<property>NATIVE_LIBS_DIR_PATH</property>
|
||||
</notImportedProperties>
|
||||
</configuration>
|
||||
<configuration />
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="android-support-v4" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
204
mobile/build-test.xml
Normal file
204
mobile/build-test.xml
Normal file
@ -0,0 +1,204 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="IITC_Mobile" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var.
|
||||
This must be done before we load project.properties since
|
||||
the proguard config can use sdk.dir -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- allow the package name to be overridden when building -->
|
||||
<property name="override.package.name" value="com.cradle.iitc_mobile.test"/>
|
||||
|
||||
<!-- Puts the project's resources into the output package file
|
||||
This actually can create multiple resource package in case
|
||||
Some custom apk with specific configuration have been
|
||||
declared in default.properties.
|
||||
-->
|
||||
<target name="-package-resources" depends="-crunch">
|
||||
<!-- only package resources if *not* a library project -->
|
||||
<do-only-if-not-library elseText="Library project: do not package resources..." >
|
||||
<aapt executable="${aapt}"
|
||||
command="package"
|
||||
versioncode="${version.code}"
|
||||
versionname="${version.name}"
|
||||
debug="${build.is.packaging.debug}"
|
||||
manifest="${out.manifest.abs.file}"
|
||||
manifestpackage="${override.package.name}"
|
||||
assets="${asset.absolute.dir}"
|
||||
androidjar="${project.target.android.jar}"
|
||||
apkfolder="${out.absolute.dir}"
|
||||
nocrunch="${build.packaging.nocrunch}"
|
||||
resourcefilename="${resource.package.file.name}"
|
||||
resourcefilter="${aapt.resource.filter}"
|
||||
libraryResFolderPathRefid="project.library.res.folder.path"
|
||||
libraryPackagesRefid="project.library.packages"
|
||||
libraryRFileRefid="project.library.bin.r.file.path"
|
||||
previousBuildType="${build.last.target}"
|
||||
buildType="${build.target}"
|
||||
ignoreAssets="${aapt.ignore.assets}">
|
||||
<res path="${out.res.absolute.dir}" />
|
||||
<res path="${resource.absolute.dir}" />
|
||||
<!-- <nocompress /> forces no compression on any files in assets or res/raw -->
|
||||
<!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
|
||||
</aapt>
|
||||
</do-only-if-not-library>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-pre-build" depends="-custom-git-version,-custom-manifest-version,-test-setup">
|
||||
</target>
|
||||
|
||||
<!-- Packages the application. -->
|
||||
<target name="-post-build">
|
||||
<antcall target="-custom-restore-manifest"/>
|
||||
<antcall target="-test-revert"/>
|
||||
</target>
|
||||
|
||||
<!-- Custom targets -->
|
||||
<target name="-custom-git-version">
|
||||
<exec executable="sh" outputproperty="git.commits">
|
||||
<arg value="-c" />
|
||||
<arg value="git log --pretty=format:'' | wc -l" />
|
||||
</exec>
|
||||
<echo>git.commits: ${git.commits}</echo>
|
||||
<exec executable="git" outputproperty="git.version">
|
||||
<arg value="rev-parse" />
|
||||
<arg value="--short" />
|
||||
<arg value="HEAD" />
|
||||
</exec>
|
||||
<echo>git.version: ${git.version}</echo>
|
||||
</target>
|
||||
|
||||
<target name="-custom-manifest-version">
|
||||
<echo>Creating backup of AndroidManifest.xml</echo>
|
||||
<copy file="AndroidManifest.xml" tofile="AndroidManifest.xml.antbak" preservelastmodified="true" />
|
||||
|
||||
<replaceregexp
|
||||
file="AndroidManifest.xml"
|
||||
match='android:versionCode="(\d+)"'
|
||||
replace='android:versionCode="${git.commits}"' />
|
||||
|
||||
<replaceregexp
|
||||
file="AndroidManifest.xml"
|
||||
match='android:versionName="(\d+\.\d+)"'
|
||||
replace='android:versionName="\1.${git.version}"' />
|
||||
</target>
|
||||
|
||||
<target name="-custom-restore-manifest">
|
||||
<echo>Restoring backup of AndroidManifest.xml</echo>
|
||||
<move file="AndroidManifest.xml.antbak"
|
||||
tofile="AndroidManifest.xml"
|
||||
preservelastmodified="true"
|
||||
overwrite="true" />
|
||||
</target>
|
||||
|
||||
<target name="-test-setup">
|
||||
<echo>Creating backup of strings.xml and preferences.xml</echo>
|
||||
<copy file="res/values/strings.xml" tofile="strings.xml.antbak" preservelastmodified="true" />
|
||||
<copy file="res/xml/preferences.xml" tofile="preferences.xml.antbak" preservelastmodified="true" />
|
||||
<replaceregexp
|
||||
file="res/values/strings.xml"
|
||||
match='IITC Mobile'
|
||||
replace='IITCm Test'/>
|
||||
<replaceregexp
|
||||
file="res/xml/preferences.xml"
|
||||
match='targetPackage="com.cradle.iitc_mobile"'
|
||||
replace='targetPackage="com.cradle.iitc_mobile.test"'/>
|
||||
</target>
|
||||
|
||||
<target name="-test-revert">
|
||||
<echo>Restoring backup of strings.xml and preferences.xml</echo>
|
||||
<move file="strings.xml.antbak"
|
||||
tofile="res/values/strings.xml"
|
||||
preservelastmodified="true"
|
||||
overwrite="true" />
|
||||
<move file="preferences.xml.antbak"
|
||||
tofile="res/xml/preferences.xml"
|
||||
preservelastmodified="true"
|
||||
overwrite="true" />
|
||||
</target>
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
@ -1,35 +0,0 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:0.4'
|
||||
}
|
||||
}
|
||||
apply plugin: 'android'
|
||||
|
||||
dependencies {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 17
|
||||
buildToolsVersion "17"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 17
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
resources.srcDirs = ['src']
|
||||
aidl.srcDirs = ['src']
|
||||
renderscript.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
}
|
||||
|
||||
instrumentTest.setRoot('tests')
|
||||
}
|
||||
}
|
@ -87,44 +87,6 @@
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
|
||||
<!-- allow the package name to be overridden when building -->
|
||||
<property name="override.package.name" value="com.cradle.iitc_mobile"/>
|
||||
|
||||
<!-- Puts the project's resources into the output package file
|
||||
This actually can create multiple resource package in case
|
||||
Some custom apk with specific configuration have been
|
||||
declared in default.properties.
|
||||
-->
|
||||
<target name="-package-resources" depends="-crunch">
|
||||
<!-- only package resources if *not* a library project -->
|
||||
<do-only-if-not-library elseText="Library project: do not package resources..." >
|
||||
<aapt executable="${aapt}"
|
||||
command="package"
|
||||
versioncode="${version.code}"
|
||||
versionname="${version.name}"
|
||||
debug="${build.is.packaging.debug}"
|
||||
manifest="${out.manifest.abs.file}"
|
||||
manifestpackage="${override.package.name}"
|
||||
assets="${asset.absolute.dir}"
|
||||
androidjar="${project.target.android.jar}"
|
||||
apkfolder="${out.absolute.dir}"
|
||||
nocrunch="${build.packaging.nocrunch}"
|
||||
resourcefilename="${resource.package.file.name}"
|
||||
resourcefilter="${aapt.resource.filter}"
|
||||
libraryResFolderPathRefid="project.library.res.folder.path"
|
||||
libraryPackagesRefid="project.library.packages"
|
||||
libraryRFileRefid="project.library.bin.r.file.path"
|
||||
previousBuildType="${build.last.target}"
|
||||
buildType="${build.target}"
|
||||
ignoreAssets="${aapt.ignore.assets}">
|
||||
<res path="${out.res.absolute.dir}" />
|
||||
<res path="${resource.absolute.dir}" />
|
||||
<!-- <nocompress /> forces no compression on any files in assets or res/raw -->
|
||||
<!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
|
||||
</aapt>
|
||||
</do-only-if-not-library>
|
||||
</target>
|
||||
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
# view res/xml/preferences.xml #generated:4
|
||||
-keep class com.cradle.iitc_mobile.IITC_AboutDialogPreference { <init>(...); }
|
||||
|
||||
# view AndroidManifest.xml #generated:23
|
||||
-keep class com.cradle.iitc_mobile.IITC_Mobile { <init>(...); }
|
||||
|
||||
# view AndroidManifest.xml #generated:56
|
||||
-keep class com.cradle.iitc_mobile.IITC_SearchableActivity { <init>(...); }
|
||||
|
||||
# view AndroidManifest.xml #generated:50
|
||||
-keep class com.cradle.iitc_mobile.IITC_PreferenceActivity { <init>(...); }
|
||||
|
||||
# view res/layout/activity_main.xml #generated:6
|
||||
-keep class com.cradle.iitc_mobile.IITC_WebView { <init>(...); }
|
||||
|
||||
-keep class com.cradle.iitc_mobile.IITC_JSInterface { <init>(...); }
|
@ -16,29 +16,29 @@
|
||||
<string name="locate">Get Location</string>
|
||||
<string name="local">local</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="build_version">Build Version</string>
|
||||
<string name="iitc_version">IITC Version</string>
|
||||
<string name="about">About</string>
|
||||
|
||||
<string name="pref_about_title">About IITC Mobile</string>
|
||||
<!-- Use CDATA to prevent android from parsing html tags....we are doing this with Html.fromHtml() -->
|
||||
<string name="pref_about_msg">
|
||||
<![CDATA[<big><b>Ingress Intel Total Conversion Mobile</b></big><br><br>
|
||||
<string name="pref_about_text">
|
||||
<![CDATA[
|
||||
<h1>Ingress Intel Total Conversion Mobile</h1>
|
||||
<b>Build Version: %1$s</b><br>
|
||||
<b>IITC Version: %2$s</b><br>
|
||||
<br>
|
||||
<b>by <a href="https://github.com/leCradle">cradle</a> and contributors</b><br><br>
|
||||
<b>Icon by <a href="http://www.ludolab.net">Giuseppe Lucido</a></b><br><br>
|
||||
IITC Mobile is an optimized mobile browser for the
|
||||
Ingress Intel Total Conversion (IITC) userscript by <a href="https://github.com/breunigs"><b>breunigs</b></a>.
|
||||
After Niantic asked the main developer to shut down his github project, development
|
||||
is continued on a fork of <a href="https://github.com/jonatkins"><b>jonatkins</b></a>.<br><br>
|
||||
<b>Community:</b><br>
|
||||
is continued on a fork of <a href="https://github.com/jonatkins"><b>jonatkins</b></a>.
|
||||
<h3>Community:</h3>
|
||||
• Visit the <a href="http://iitc.jonatkins.com/">IITC website</a> for new releases and the desktop version.<br>
|
||||
• Follow the <a href="https://plus.google.com/105383756361375410867">IITC Google+ page</a>
|
||||
for release announcements.<br>
|
||||
• Join the <a href="https://plus.google.com/communities/105647403088015055797">IITC Google+ community</a>
|
||||
- a place to ask for help and discuss with other users.<br><br>
|
||||
<b>Developers:</b><br>
|
||||
<a href="https://github.com/jonatkins/ingress-intel-total-conversion">IITC on Github</a><br><br>
|
||||
<b>IITC Licence:</b><br>
|
||||
- a place to ask for help and discuss with other users.
|
||||
<h3>Developers:</h3>
|
||||
<a href="https://github.com/jonatkins/ingress-intel-total-conversion">IITC on Github</a>
|
||||
<h3>IITC Licence:</h3>
|
||||
Copyright © 2013 Stefan Breunig, Jon Atkins, Philipp Schäfer and others<br><br>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for
|
||||
@ -53,7 +53,8 @@
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.]]>
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
]]>
|
||||
</string>
|
||||
<string name="notice_drawers">
|
||||
<![CDATA[IITCm recently changed its navigation structure. How to use it:<br><br>
|
||||
@ -67,24 +68,30 @@
|
||||
• tap and hold a portal for a second<br>
|
||||
• tap on the left half of the status bar]]>
|
||||
</string>
|
||||
|
||||
|
||||
<string name="pref_ui_cat">UI</string>
|
||||
<string name="pref_misc_cat">Misc</string>
|
||||
<string name="pref_developer_options_cat">Developer options</string>
|
||||
<string name="pref_tweaks_cat">Tweaks</string>
|
||||
<string name="pref_plugins">IITC Plugins</string>
|
||||
<string name="pref_plugins_title">Available plugins</string>
|
||||
<string name="pref_user_loc">Display user location</string>
|
||||
<string name="pref_user_loc_sum">Show users position on map</string>
|
||||
<string name="pref_user_zoom">Show zoom control</string>
|
||||
<string name="pref_user_zoom_sum">Shows +/- buttons even on multitouch capable devices.</string>
|
||||
<string name="pref_fullscreen_actionbar">Hide Action Bar in fullscreen mode</string>
|
||||
<string name="pref_fullscreen_actionbar_sum">Nice for screenshots. Note: IITCm can still be controlled via the Navigation Drawers</string>
|
||||
<string name="pref_fullscreen">Hide in fullscreen mode</string>
|
||||
<string name="pref_fullscreen_sum">Which elements should be hidden in fullscreen mode.
|
||||
Note: IITCm can still be controlled via the Navigation Drawers</string>
|
||||
<string name="pref_force_desktop">Force desktop mode</string>
|
||||
<string name="pref_force_desktop_sum">Nice for tablets, looks awful on smartphones</string>
|
||||
<string name="pref_force_https">Force https</string>
|
||||
<string name="pref_force_https_sum">Disabling may improve performance</string>
|
||||
<string name="pref_external_storage">Move cache to external storage</string>
|
||||
<string name="pref_external_storage_sum">Restart required! Write cache to sdCard. Saves internal storage.
|
||||
External storage has to be mounted.</string>
|
||||
<string name="pref_press_twice_to_exit">Press back button twice to exit</string>
|
||||
<string name="pref_press_twice_to_exit_sum">Avoids accidental exits</string>
|
||||
<string name="pref_developer_options">Developer options</string>
|
||||
<string name="pref_advanced_options">Advanced settings</string>
|
||||
<string name="pref_enable_dev_mode">Enable developer mode</string>
|
||||
<string name="pref_enable_dev_mode_sum">If enabled, all IITC sources will be loaded from external storage of the Android device.
|
||||
Please copy all sources from $IITC_folder/build/mobile/ to /sdcard/IITC_Mobile/dev/.</string>
|
||||
@ -92,9 +99,40 @@
|
||||
<string name="pref_advanced_menu_sum">In addition to the default IITC buttons the advanced menu
|
||||
contains a debug pane plus an option to clear cookies</string>
|
||||
<string name="pref_disable_splash">Disable Splash Screen</string>
|
||||
<string name="pref_fake_user_agent">Fake User Agent</string>
|
||||
<string name="pref_fake_user_agent_sum">Let IITCm appear as a desktop browser for the intel site.
|
||||
Note: If just want to use the desktop mode use the \'force desktop mode\' setting</string>
|
||||
<string name="pref_select_iitc">IITC source</string>
|
||||
<string name="pref_select_iitc_sum">Load IITC main script from url or use local script. Currently used source:</string>
|
||||
|
||||
<string name="pref_caching">Aggressive Caching</string>
|
||||
<string name="pref_caching_sum">Prefer cached values even if they are expired…saves traffic but
|
||||
may result in login issues</string>
|
||||
|
||||
<string-array name="pref_hide_fullscreen">
|
||||
<item>System Bar</item>
|
||||
<item>Action Bar</item>
|
||||
<item>IITC Status Bar</item>
|
||||
<item>Navigation Bar</item>
|
||||
</string-array>
|
||||
<string-array name="pref_hide_fullscreen_vals">
|
||||
<item>2</item>
|
||||
<item>4</item>
|
||||
<item>8</item>
|
||||
<item>16</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_caching_array">
|
||||
<item>Always</item>
|
||||
<item>Mobile data only (default)</item>
|
||||
<item>Never</item>
|
||||
</string-array>
|
||||
<string-array name="pref_caching_array_vals">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</string-array>
|
||||
|
||||
<string name="menu_clear_cookies">Clear Cookies</string>
|
||||
<string name="menu_search">Search</string>
|
||||
<string name="choose_account_to_login">Choose account to login</string>
|
||||
|
@ -1,99 +1,121 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<com.cradle.iitc_mobile.IITC_AboutDialogPreference
|
||||
android:key="pref_about"
|
||||
android:title="@string/pref_about_title"
|
||||
android:dialogIcon="@android:drawable/ic_dialog_info"
|
||||
android:negativeButtonText=""
|
||||
android:positiveButtonText=""
|
||||
android:dialogTitle="@string/pref_about_title"/>
|
||||
<PreferenceScreen
|
||||
android:key="pref_about_screen"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_about_title">
|
||||
<com.cradle.iitc_mobile.IITC_AboutDialogPreference
|
||||
android:dialogIcon="@android:drawable/ic_dialog_info"
|
||||
android:key="pref_about"
|
||||
android:title="@string/pref_about_title"/>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="pref_about_cat"
|
||||
android:key="pref_ui_cat"
|
||||
android:title="@string/pref_ui_cat">
|
||||
<CheckBoxPreference
|
||||
android:key="pref_user_loc"
|
||||
android:title="@string/pref_user_loc"
|
||||
android:summary="@string/pref_user_loc_sum"
|
||||
android:defaultValue="false" />
|
||||
android:defaultValue="false"
|
||||
android:key="pref_user_loc"
|
||||
android:summary="@string/pref_user_loc_sum"
|
||||
android:title="@string/pref_user_loc"/>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_user_zoom"
|
||||
android:title="@string/pref_user_zoom"
|
||||
android:summary="@string/pref_user_zoom_sum"
|
||||
android:defaultValue="false" />
|
||||
android:title="@string/pref_user_zoom"/>
|
||||
<MultiSelectListPreference
|
||||
android:key="pref_fullscreen"
|
||||
android:summary="@string/pref_fullscreen_sum"
|
||||
android:title="@string/pref_fullscreen"
|
||||
android:entries="@array/pref_hide_fullscreen"
|
||||
android:entryValues="@array/pref_hide_fullscreen_vals"/>
|
||||
<CheckBoxPreference
|
||||
android:key="pref_fullscreen_actionbar"
|
||||
android:title="@string/pref_fullscreen_actionbar"
|
||||
android:summary="@string/pref_fullscreen_actionbar_sum"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="pref_force_desktop"
|
||||
android:title="@string/pref_force_desktop"
|
||||
android:defaultValue="false"
|
||||
android:key="pref_force_desktop"
|
||||
android:summary="@string/pref_force_desktop_sum"
|
||||
android:defaultValue="false" />
|
||||
android:title="@string/pref_force_desktop"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="pref_mics"
|
||||
android:title="@string/pref_misc_cat">
|
||||
|
||||
<!-- summary is set in settings fragment -->
|
||||
<EditTextPreference
|
||||
android:defaultValue="local"
|
||||
android:key="pref_iitc_source"
|
||||
android:title="@string/pref_select_iitc"
|
||||
android:defaultValue="local"/>
|
||||
android:title="@string/pref_select_iitc"/>
|
||||
|
||||
<PreferenceScreen
|
||||
android:fragment="com.cradle.iitc_mobile.fragments.PluginsFragment"
|
||||
android:key="pref_plugins"
|
||||
android:title="@string/pref_plugins" >
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_plugins">
|
||||
<intent
|
||||
android:targetPackage="com.cradle.iitc_mobile"
|
||||
android:targetClass="com.cradle.iitc_mobile.IITC_PluginPreferenceActivity"/>
|
||||
android:targetClass="com.cradle.iitc_mobile.IITC_PluginPreferenceActivity"
|
||||
android:targetPackage="com.cradle.iitc_mobile"/>
|
||||
</PreferenceScreen>
|
||||
<CheckBoxPreference
|
||||
android:key="pref_force_https"
|
||||
android:title="@string/pref_force_https"
|
||||
android:summary="@string/pref_force_https_sum"
|
||||
android:defaultValue="true" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="pref_force_https"
|
||||
android:summary="@string/pref_force_https_sum"
|
||||
android:title="@string/pref_force_https"/>
|
||||
<CheckBoxPreference
|
||||
android:key="pref_external_storage"
|
||||
android:title="@string/pref_external_storage"
|
||||
android:summary="@string/pref_external_storage_sum"
|
||||
android:defaultValue="false" />
|
||||
<CheckBoxPreference
|
||||
android:key="pref_press_twice_to_exit"
|
||||
android:title="@string/pref_press_twice_to_exit"
|
||||
android:summary="@string/pref_press_twice_to_exit_sum"
|
||||
android:defaultValue="false" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="pref_developer_options"
|
||||
android:title="@string/pref_developer_options">
|
||||
android:title="@string/pref_developer_options_cat">
|
||||
<PreferenceScreen
|
||||
android:key="pref_developer_screen"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_advanced_options">
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_dev_checkbox"
|
||||
android:summary="@string/pref_enable_dev_mode_sum"
|
||||
android:title="@string/pref_enable_dev_mode"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_dev_checkbox"
|
||||
android:title="@string/pref_enable_dev_mode"
|
||||
android:summary="@string/pref_enable_dev_mode_sum"
|
||||
android:defaultValue="false" />
|
||||
<PreferenceCategory
|
||||
android:key="pref_advanced_ui_cat"
|
||||
android:title="@string/pref_ui_cat">
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_advanced_menu"
|
||||
android:summary="@string/pref_advanced_menu_sum"
|
||||
android:title="@string/pref_advanced_menu"/>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_disable_splash"
|
||||
android:title="@string/pref_disable_splash"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:key="pref_advanced_tweaks_cat"
|
||||
android:title="@string/pref_tweaks_cat">
|
||||
<ListPreference
|
||||
android:defaultValue="1"
|
||||
android:entries="@array/pref_caching_array"
|
||||
android:entryValues="@array/pref_caching_array_vals"
|
||||
android:key="pref_caching"
|
||||
android:summary="@string/pref_caching_sum"
|
||||
android:title="@string/pref_caching"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_advanced_menu"
|
||||
android:title="@string/pref_advanced_menu"
|
||||
android:summary="@string/pref_advanced_menu_sum"
|
||||
android:defaultValue="false" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_disable_splash"
|
||||
android:title="@string/pref_disable_splash"
|
||||
android:defaultValue="false" />
|
||||
|
||||
<ListPreference
|
||||
android:key="pref_build_version"
|
||||
android:title="@string/build_version"
|
||||
android:enabled="false"
|
||||
android:selectable="false" />
|
||||
|
||||
<ListPreference
|
||||
android:key="pref_iitc_version"
|
||||
android:title="@string/iitc_version"
|
||||
android:enabled="false"
|
||||
android:selectable="false" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_fake_user_agent"
|
||||
android:summary="@string/pref_fake_user_agent_sum"
|
||||
android:title="@string/pref_fake_user_agent"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
|
@ -1,44 +1,41 @@
|
||||
package com.cradle.iitc_mobile;
|
||||
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.preference.DialogPreference;
|
||||
import android.preference.Preference;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class IITC_AboutDialogPreference extends DialogPreference {
|
||||
|
||||
private final Context mContext;
|
||||
public class IITC_AboutDialogPreference extends Preference {
|
||||
private String mBuildVersion = "";
|
||||
private String mIitcVersion = "";
|
||||
|
||||
public IITC_AboutDialogPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
this.mContext = context;
|
||||
}
|
||||
|
||||
/*
|
||||
* start an about-dialog...I found no better way for clickable
|
||||
* links in a TextView then using Html.fromHtml...Linkify is just broken and
|
||||
* does not understand html href tags...so let's tag the @string/about_msg
|
||||
* with CDATA and use Html.fromHtml(...) for clickable hrefs with tags.
|
||||
*/
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(Builder builder) {
|
||||
final TextView message = new TextView(mContext);
|
||||
String about_msg = mContext.getText(R.string.pref_about_msg).toString();
|
||||
message.setText(Html.fromHtml(about_msg));
|
||||
message.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
builder.setView(message).setTitle(R.string.about)
|
||||
.setIcon(android.R.drawable.ic_dialog_info)
|
||||
.setNeutralButton(R.string.close, new OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
super.onPrepareDialogBuilder(builder);
|
||||
public View getView(View convertView, ViewGroup parent) {
|
||||
/*
|
||||
* I found no better way for clickable links in a TextView then using Html.fromHtml(). Linkify
|
||||
* is just broken and does not understand html href tags, so let's tag the @string/about_msg
|
||||
* with CDATA and use Html.fromHtml() for clickable hrefs with tags.
|
||||
*/
|
||||
final TextView tv = new TextView(getContext());
|
||||
String text = getContext().getText(R.string.pref_about_text).toString();
|
||||
text = String.format(text, mBuildVersion, mIitcVersion);
|
||||
|
||||
tv.setText(Html.fromHtml(text));
|
||||
tv.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
return tv;
|
||||
}
|
||||
|
||||
public void setVersions(String iitcVersion, String buildVersion) {
|
||||
mIitcVersion = iitcVersion;
|
||||
mBuildVersion = buildVersion;
|
||||
}
|
||||
}
|
||||
|
23
mobile/src/com/cradle/iitc_mobile/IITC_Application.java
Normal file
23
mobile/src/com/cradle/iitc_mobile/IITC_Application.java
Normal file
@ -0,0 +1,23 @@
|
||||
package com.cradle.iitc_mobile;
|
||||
|
||||
import android.app.Application;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/*
|
||||
* To write the WebView cache to external storage we need to override the
|
||||
* getCacheDir method of the main application. Some internal Android code seems
|
||||
* to call getApplicationContext().getCacheDir(); instead of
|
||||
* getContext().getCacheDir(); to decide where to store and read cached files.
|
||||
*/
|
||||
public class IITC_Application extends Application {
|
||||
@Override
|
||||
public File getCacheDir() {
|
||||
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("pref_external_storage", false)) {
|
||||
return (getExternalCacheDir() != null) ? getExternalCacheDir() : super.getCacheDir();
|
||||
} else {
|
||||
return super.getCacheDir();
|
||||
}
|
||||
}
|
||||
}
|
@ -128,10 +128,12 @@ public class IITC_DeviceAccountLogin implements AccountManagerCallback<Bundle> {
|
||||
*/
|
||||
public void onActivityResult(int resultCode, Intent data) {
|
||||
if (resultCode == Activity.RESULT_OK)
|
||||
// authentication activity succeeded, request token again
|
||||
// authentication activity succeeded, request token again
|
||||
{
|
||||
startAuthentication();
|
||||
else
|
||||
} else {
|
||||
onLoginFailed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,7 +18,7 @@ import java.util.Locale;
|
||||
// provide communication between IITC script and android app
|
||||
public class IITC_JSInterface {
|
||||
// context of main activity
|
||||
private IITC_Mobile mIitc;
|
||||
private final IITC_Mobile mIitc;
|
||||
|
||||
IITC_JSInterface(IITC_Mobile iitc) {
|
||||
mIitc = iitc;
|
||||
@ -76,6 +76,19 @@ public class IITC_JSInterface {
|
||||
return versionCode;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public String getVersionName() {
|
||||
String buildVersion = "unknown";
|
||||
PackageManager pm = mIitc.getPackageManager();
|
||||
try {
|
||||
PackageInfo info = pm.getPackageInfo(mIitc.getPackageName(), 0);
|
||||
buildVersion = info.versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return buildVersion;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void switchToPane(final String id) {
|
||||
mIitc.runOnUiThread(new Runnable() {
|
||||
@ -111,7 +124,7 @@ public class IITC_JSInterface {
|
||||
@Override
|
||||
public void run() {
|
||||
mIitc.setLoadingState(false);
|
||||
|
||||
|
||||
mIitc.getMapSettings().onBootFinished();
|
||||
}
|
||||
});
|
||||
|
@ -22,7 +22,7 @@ import java.util.Comparator;
|
||||
|
||||
public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickListener, OnItemLongClickListener {
|
||||
private class HighlighterAdapter extends ArrayAdapter<String> {
|
||||
private HighlighterComparator mComparator = new HighlighterComparator();
|
||||
private final HighlighterComparator mComparator = new HighlighterComparator();
|
||||
|
||||
private HighlighterAdapter(int resource) {
|
||||
super(mIitc, resource);
|
||||
@ -47,12 +47,13 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList
|
||||
@Override
|
||||
public int compare(String lhs, String rhs) {
|
||||
// Move "No Highlights" on top. Sort the rest alphabetically
|
||||
if (lhs.equals("No Highlights"))
|
||||
if (lhs.equals("No Highlights")) {
|
||||
return -1000;
|
||||
else if (rhs.equals("No Highlights"))
|
||||
} else if (rhs.equals("No Highlights")) {
|
||||
return 1000;
|
||||
else
|
||||
} else {
|
||||
return lhs.compareTo(rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,8 +68,7 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList
|
||||
}
|
||||
}
|
||||
|
||||
private class LayerAdapter extends ArrayAdapter<Layer>
|
||||
{
|
||||
private class LayerAdapter extends ArrayAdapter<Layer> {
|
||||
public LayerAdapter(int resource) {
|
||||
super(mIitc, resource);
|
||||
}
|
||||
@ -78,21 +78,22 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList
|
||||
Layer item = getItem(position);
|
||||
View view = (TextView) super.getView(position, convertView, parent);
|
||||
|
||||
if (view instanceof CheckedTextView)
|
||||
if (view instanceof CheckedTextView) {
|
||||
((CheckedTextView) view).setChecked(item.active);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
private IITC_Mobile mIitc;
|
||||
private final IITC_Mobile mIitc;
|
||||
|
||||
private ArrayAdapter<String> mHighlighters;
|
||||
private ArrayAdapter<Layer> mBaseLayers;
|
||||
private ArrayAdapter<Layer> mOverlayLayers;
|
||||
private final ArrayAdapter<String> mHighlighters;
|
||||
private final ArrayAdapter<Layer> mBaseLayers;
|
||||
private final ArrayAdapter<Layer> mOverlayLayers;
|
||||
|
||||
private Spinner mSpinnerBaseMap;
|
||||
private Spinner mSpinnerHighlighter;
|
||||
private ListView mListViewOverlayLayers;
|
||||
private final Spinner mSpinnerBaseMap;
|
||||
private final Spinner mSpinnerHighlighter;
|
||||
private final ListView mListViewOverlayLayers;
|
||||
|
||||
private String mActiveHighlighter;
|
||||
private int mActiveLayer;
|
||||
@ -129,9 +130,10 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList
|
||||
}
|
||||
|
||||
private void setLayer(Layer layer) {
|
||||
if (!mLoading)
|
||||
if (!mLoading) {
|
||||
mIitc.getWebView().loadUrl(
|
||||
"javascript: window.layerChooser.showLayer(" + layer.id + "," + layer.active + ");");
|
||||
}
|
||||
}
|
||||
|
||||
public void addPortalHighlighter(String name) {
|
||||
@ -181,8 +183,7 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList
|
||||
if (parent.equals(mSpinnerHighlighter)) {
|
||||
String name = mHighlighters.getItem(position);
|
||||
mIitc.getWebView().loadUrl("javascript: window.changePortalHighlights('" + name + "')");
|
||||
}
|
||||
else if (parent.equals(mSpinnerBaseMap)) {
|
||||
} else if (parent.equals(mSpinnerBaseMap)) {
|
||||
mBaseLayers.getItem(mActiveLayer).active = false; // set old layer to hidden, but no need to really hide
|
||||
|
||||
Layer layer = mBaseLayers.getItem(position);
|
||||
@ -210,8 +211,9 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList
|
||||
mActiveHighlighter = name;
|
||||
|
||||
int position = mHighlighters.getPosition(mActiveHighlighter);
|
||||
if (position >= 0 && position < mHighlighters.getCount())
|
||||
if (position >= 0 && position < mHighlighters.getCount()) {
|
||||
mSpinnerHighlighter.setSelection(position);
|
||||
}
|
||||
|
||||
mIitc.getNavigationHelper().setHighlighter(name);
|
||||
}
|
||||
@ -247,13 +249,14 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList
|
||||
layer.active = layerObj.getBoolean("active");
|
||||
|
||||
if (layer.active)
|
||||
// getCount() will be the index of the layer we are about to add
|
||||
// getCount() will be the index of the layer we are about to add
|
||||
{
|
||||
mActiveLayer = mBaseLayers.getCount();
|
||||
}
|
||||
|
||||
mBaseLayers.add(layer);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mBaseLayers.notifyDataSetChanged();
|
||||
@ -273,14 +276,14 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList
|
||||
mOverlayLayers.add(layer);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mOverlayLayers.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void updateLayers() {
|
||||
if (!mLoading)
|
||||
if (!mLoading) {
|
||||
mIitc.getWebView().loadUrl("javascript: window.layerChooser.getLayers()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,32 +22,28 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.cradle.iitc_mobile.IITC_NavigationHelper.Pane;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Locale;
|
||||
import java.util.Stack;
|
||||
|
||||
public class IITC_Mobile extends Activity {
|
||||
public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeListener, LocationListener {
|
||||
|
||||
private static final int REQUEST_LOGIN = 1;
|
||||
|
||||
private IITC_WebView mIitcWebView;
|
||||
private OnSharedPreferenceChangeListener mSharedPrefChangeListener;
|
||||
private final String mIntelUrl = "https://www.ingress.com/intel";
|
||||
private boolean mIsLocEnabled = false;
|
||||
private Location mLastLocation = null;
|
||||
private LocationManager mLocMngr = null;
|
||||
private LocationListener mLocListener = null;
|
||||
private boolean mFullscreenMode = false;
|
||||
private IITC_DeviceAccountLogin mLogin;
|
||||
private MenuItem mSearchMenuItem;
|
||||
private boolean mDesktopMode = false;
|
||||
@ -74,46 +70,9 @@ public class IITC_Mobile extends Activity {
|
||||
setContentView(R.layout.activity_main);
|
||||
mIitcWebView = (IITC_WebView) findViewById(R.id.iitc_webview);
|
||||
|
||||
// pass ActionBar to helper because we deprecated getActionBar
|
||||
mNavigationHelper = new IITC_NavigationHelper(this, super.getActionBar());
|
||||
|
||||
mMapSettings = new IITC_MapSettings(this);
|
||||
|
||||
// do something if user changed something in the settings
|
||||
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
mSharedPrefChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(
|
||||
SharedPreferences sharedPreferences, String key) {
|
||||
if (key.equals("pref_force_desktop")) {
|
||||
mDesktopMode = sharedPreferences.getBoolean("pref_force_desktop", false);
|
||||
mNavigationHelper.onPrefChanged();
|
||||
}
|
||||
if (key.equals("pref_user_loc"))
|
||||
mIsLocEnabled = sharedPreferences.getBoolean("pref_user_loc",
|
||||
false);
|
||||
if (key.equals("pref_fullscreen_actionbar")) {
|
||||
mNavigationHelper.onPrefChanged();
|
||||
return;
|
||||
}
|
||||
if (key.equals("pref_advanced_menu")) {
|
||||
mAdvancedMenu = sharedPreferences.getBoolean("pref_advanced_menu", false);
|
||||
mNavigationHelper.setDebugMode(mAdvancedMenu);
|
||||
invalidateOptionsMenu();
|
||||
// no reload needed
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.equals("pref_press_twice_to_exit")
|
||||
|| key.equals("pref_share_selected_tab")
|
||||
|| key.equals("pref_messages"))
|
||||
// no reload needed
|
||||
return;
|
||||
|
||||
mReloadNeeded = true;
|
||||
}
|
||||
};
|
||||
mSharedPrefs.registerOnSharedPreferenceChangeListener(mSharedPrefChangeListener);
|
||||
mSharedPrefs.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
// enable/disable mDesktopMode mode on menu create and url load
|
||||
mDesktopMode = mSharedPrefs.getBoolean("pref_force_desktop", false);
|
||||
@ -121,45 +80,95 @@ public class IITC_Mobile extends Activity {
|
||||
// enable/disable advance menu
|
||||
mAdvancedMenu = mSharedPrefs.getBoolean("pref_advanced_menu", false);
|
||||
|
||||
// get fullscreen status from settings
|
||||
mIitcWebView.updateFullscreenStatus();
|
||||
|
||||
// Acquire a reference to the system Location Manager
|
||||
mLocMngr = (LocationManager) this
|
||||
.getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
// Define a mSharedPrefChangeListener that responds to location updates
|
||||
mLocListener = new LocationListener() {
|
||||
public void onLocationChanged(Location location) {
|
||||
// Called when a new location is found by the network location
|
||||
// provider.
|
||||
drawMarker(location);
|
||||
mLastLocation = location;
|
||||
}
|
||||
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
}
|
||||
|
||||
public void onProviderEnabled(String provider) {
|
||||
}
|
||||
|
||||
public void onProviderDisabled(String provider) {
|
||||
}
|
||||
};
|
||||
|
||||
mIsLocEnabled = mSharedPrefs.getBoolean("pref_user_loc", false);
|
||||
if (mIsLocEnabled) {
|
||||
// Register the mSharedPrefChangeListener with the Location Manager to receive
|
||||
// location updates
|
||||
mLocMngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
|
||||
0, 0, mLocListener);
|
||||
0, 0, this);
|
||||
mLocMngr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
|
||||
mLocListener);
|
||||
this);
|
||||
}
|
||||
|
||||
// pass ActionBar to helper because we deprecated getActionBar
|
||||
mNavigationHelper = new IITC_NavigationHelper(this, super.getActionBar());
|
||||
|
||||
mMapSettings = new IITC_MapSettings(this);
|
||||
|
||||
|
||||
// Clear the back stack
|
||||
mBackStack.clear();
|
||||
|
||||
handleIntent(getIntent(), true);
|
||||
}
|
||||
|
||||
// --------------------- onSharedPreferenceListener -----------------------
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (key.equals("pref_force_desktop")) {
|
||||
mDesktopMode = sharedPreferences.getBoolean("pref_force_desktop", false);
|
||||
mNavigationHelper.onPrefChanged();
|
||||
} else if (key.equals("pref_user_loc")) {
|
||||
mIsLocEnabled = sharedPreferences.getBoolean("pref_user_loc", false);
|
||||
} else if (key.equals("pref_fullscreen")) {
|
||||
mIitcWebView.updateFullscreenStatus();
|
||||
mNavigationHelper.onPrefChanged();
|
||||
return;
|
||||
} else if (key.equals("pref_advanced_menu")) {
|
||||
mAdvancedMenu = sharedPreferences.getBoolean("pref_advanced_menu", false);
|
||||
mNavigationHelper.setDebugMode(mAdvancedMenu);
|
||||
invalidateOptionsMenu();
|
||||
// no reload needed
|
||||
return;
|
||||
} else if (key.equals("pref_fake_user_agent")) {
|
||||
mIitcWebView.setUserAgent();
|
||||
} else if (key.equals("pref_caching")) {
|
||||
mIitcWebView.updateCaching(false);
|
||||
} else if (key.equals("pref_press_twice_to_exit")
|
||||
|| key.equals("pref_share_selected_tab")
|
||||
|| key.equals("pref_messages")
|
||||
|| key.equals("pref_external_storage"))
|
||||
// no reload needed
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mReloadNeeded = true;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// ------------------------ LocationListener ------------------------------
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
// Called when a new location is found by the network location
|
||||
// provider.
|
||||
drawMarker(location);
|
||||
mLastLocation = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(String provider) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(String provider) {
|
||||
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
setIntent(intent);
|
||||
@ -228,8 +237,9 @@ public class IITC_Mobile extends Activity {
|
||||
|
||||
// parts[0] may contain an 'uncertainty' parameter, delimited by a semicolon
|
||||
String[] pos = parts[0].split(";", 2)[0].split(",", 2);
|
||||
if (pos.length != 2)
|
||||
if (pos.length != 2) {
|
||||
throw new URISyntaxException(uri.toString(), "URI does not contain a valid position");
|
||||
}
|
||||
|
||||
try {
|
||||
lat = Double.valueOf(pos[0]);
|
||||
@ -257,8 +267,9 @@ public class IITC_Mobile extends Activity {
|
||||
}
|
||||
|
||||
String url = "http://www.ingress.com/intel?ll=" + lat + "," + lon;
|
||||
if (z != null)
|
||||
if (z != null) {
|
||||
url += "&z=" + z;
|
||||
}
|
||||
this.loadUrl(url);
|
||||
}
|
||||
|
||||
@ -268,20 +279,19 @@ public class IITC_Mobile extends Activity {
|
||||
|
||||
// enough idle...let's do some work
|
||||
Log.d("iitcm", "resuming...reset idleTimer");
|
||||
mIitcWebView.updateCaching();
|
||||
mIitcWebView.updateCaching(false);
|
||||
|
||||
if (mIsLocEnabled) {
|
||||
// Register the mSharedPrefChangeListener with the Location Manager to receive
|
||||
// location updates
|
||||
mLocMngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocListener);
|
||||
mLocMngr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocListener);
|
||||
mLocMngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
|
||||
mLocMngr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
|
||||
}
|
||||
|
||||
if (mReloadNeeded) {
|
||||
Log.d("iitcm", "preference had changed...reload needed");
|
||||
reloadIITC();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// iitc is not fully booted...timer will be reset by the script itself
|
||||
if (findViewById(R.id.imageLoading).getVisibility() == View.GONE) {
|
||||
mIitcWebView.loadUrl("javascript: window.idleReset();");
|
||||
@ -294,8 +304,9 @@ public class IITC_Mobile extends Activity {
|
||||
Log.d("iitcm", "stopping iitcm");
|
||||
mIitcWebView.loadUrl("javascript: window.idleSet();");
|
||||
|
||||
if (mIsLocEnabled)
|
||||
mLocMngr.removeUpdates(mLocListener);
|
||||
if (mIsLocEnabled) {
|
||||
mLocMngr.removeUpdates(this);
|
||||
}
|
||||
|
||||
super.onStop();
|
||||
}
|
||||
@ -321,8 +332,8 @@ public class IITC_Mobile extends Activity {
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// exit fullscreen mode if it is enabled and action bar is disabled or the back stack is empty
|
||||
if (mFullscreenMode && (mBackStack.isEmpty() || mNavigationHelper.hideInFullscreen())) {
|
||||
toggleFullscreen();
|
||||
if (mIitcWebView.isInFullscreen() && mBackStack.isEmpty()) {
|
||||
mIitcWebView.toggleFullscreen();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -350,7 +361,6 @@ public class IITC_Mobile extends Activity {
|
||||
|
||||
if (mBackButtonPressed || !mSharedPrefs.getBoolean("pref_press_twice_to_exit", false)) {
|
||||
super.onBackPressed();
|
||||
return;
|
||||
} else {
|
||||
mBackButtonPressed = true;
|
||||
Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show();
|
||||
@ -380,10 +390,11 @@ public class IITC_Mobile extends Activity {
|
||||
// ensure no double adds
|
||||
if (pane == mCurrentPane) return;
|
||||
|
||||
if (mBackStackPush)
|
||||
if (mBackStackPush) {
|
||||
mBackStack.push(mCurrentPane);
|
||||
else
|
||||
} else {
|
||||
mBackStackPush = true;
|
||||
}
|
||||
|
||||
mCurrentPane = pane;
|
||||
mNavigationHelper.switchTo(pane);
|
||||
@ -430,8 +441,9 @@ public class IITC_Mobile extends Activity {
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (mNavigationHelper.onOptionsItemSelected(item))
|
||||
if (mNavigationHelper.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle item selection
|
||||
final int itemId = item.getItemId();
|
||||
@ -446,7 +458,7 @@ public class IITC_Mobile extends Activity {
|
||||
reloadIITC();
|
||||
return true;
|
||||
case R.id.toggle_fullscreen:
|
||||
toggleFullscreen();
|
||||
mIitcWebView.toggleFullscreen();
|
||||
return true;
|
||||
case R.id.layer_chooser:
|
||||
mNavigationHelper.openRightDrawer();
|
||||
@ -459,10 +471,11 @@ public class IITC_Mobile extends Activity {
|
||||
"window.map.locate({setView : true, maxZoom: 15});");
|
||||
// if gps location is displayed we can use a better location without any costs
|
||||
} else {
|
||||
if (mLastLocation != null)
|
||||
if (mLastLocation != null) {
|
||||
mIitcWebView.loadUrl("javascript: window.map.setView(new L.LatLng(" +
|
||||
mLastLocation.getLatitude() + "," +
|
||||
mLastLocation.getLongitude() + "), 15);");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case R.id.action_settings: // start settings activity
|
||||
@ -480,6 +493,11 @@ public class IITC_Mobile extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getCacheDir() {
|
||||
return getApplicationContext().getCacheDir();
|
||||
}
|
||||
|
||||
public void reloadIITC() {
|
||||
mNavigationHelper.reset();
|
||||
mMapSettings.reset();
|
||||
@ -503,10 +521,11 @@ public class IITC_Mobile extends Activity {
|
||||
|
||||
// vp=f enables mDesktopMode mode...vp=m is the defaul mobile view
|
||||
private String addUrlParam(String url) {
|
||||
if (mDesktopMode)
|
||||
if (mDesktopMode) {
|
||||
return (url + "?vp=f");
|
||||
else
|
||||
} else {
|
||||
return (url + "?vp=m");
|
||||
}
|
||||
}
|
||||
|
||||
// inject the iitc-script and load the intel url
|
||||
@ -532,16 +551,6 @@ public class IITC_Mobile extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
public void toggleFullscreen() {
|
||||
mFullscreenMode = !mFullscreenMode;
|
||||
mNavigationHelper.setFullscreen(mFullscreenMode);
|
||||
|
||||
// toggle notification bar
|
||||
WindowManager.LayoutParams attrs = getWindow().getAttributes();
|
||||
attrs.flags ^= WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
this.getWindow().setAttributes(attrs);
|
||||
}
|
||||
|
||||
public IITC_WebView getWebView() {
|
||||
return this.mIitcWebView;
|
||||
}
|
||||
@ -571,9 +580,7 @@ public class IITC_Mobile extends Activity {
|
||||
* called by IITC_WebViewClient when the Google login form is opened.
|
||||
*/
|
||||
public void onReceivedLoginRequest(IITC_WebViewClient client, WebView view,
|
||||
String realm, String account, String args) {
|
||||
Log.d("iitcm", "logging in...set caching mode to default");
|
||||
mIitcWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
String realm, String account, String args) {
|
||||
mLogin = new IITC_DeviceAccountLogin(this, view, client);
|
||||
mLogin.startLogin(realm, account, args);
|
||||
}
|
||||
@ -620,8 +627,8 @@ public class IITC_Mobile extends Activity {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated ActionBar related stuff should be handled by IITC_NavigationHelper
|
||||
* @see getNavigationHelper()
|
||||
* @deprecated ActionBar related stuff should be handled by IITC_NavigationHelper
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
|
@ -20,7 +20,6 @@ import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnItemClickListener {
|
||||
// Show/hide the up arrow on the very left
|
||||
@ -46,22 +45,23 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
add(Pane.PUBLIC);
|
||||
add(Pane.FACTION);
|
||||
|
||||
if (mPrefs.getBoolean("pref_advanced_menu", false))
|
||||
if (mPrefs.getBoolean("pref_advanced_menu", false)) {
|
||||
add(Pane.DEBUG);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
TextView view = (TextView) super.getView(position, convertView, parent);
|
||||
Pane item = getItem(position);
|
||||
if (item == Pane.MAP)
|
||||
if (item == Pane.MAP) {
|
||||
view.setText("Map");
|
||||
else
|
||||
} else {
|
||||
view.setText(getPaneTitle(item));
|
||||
}
|
||||
|
||||
int icon = 0;
|
||||
switch (item)
|
||||
{
|
||||
switch (item) {
|
||||
case MAP:
|
||||
icon = R.drawable.location_map;
|
||||
break;
|
||||
@ -85,8 +85,9 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
break;
|
||||
}
|
||||
|
||||
if (icon != 0)
|
||||
if (icon != 0) {
|
||||
view.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
@ -100,18 +101,16 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
public static final int NOTICE_INFO = 1 << 1;
|
||||
// next one would be 1<<2; (this results in 1,2,4,8,...)
|
||||
|
||||
private IITC_Mobile mIitc;
|
||||
private ActionBar mActionBar;
|
||||
private SharedPreferences mPrefs;
|
||||
private NavigationAdapter mNavigationAdapter;
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private ListView mDrawerLeft;
|
||||
private View mDrawerRight;
|
||||
private final IITC_Mobile mIitc;
|
||||
private final ActionBar mActionBar;
|
||||
private final SharedPreferences mPrefs;
|
||||
private final NavigationAdapter mNavigationAdapter;
|
||||
private final DrawerLayout mDrawerLayout;
|
||||
private final ListView mDrawerLeft;
|
||||
private final View mDrawerRight;
|
||||
|
||||
private boolean mDesktopMode = false;
|
||||
private boolean mFullscreen = false;
|
||||
private boolean mIsLoading;
|
||||
private boolean mHideInFullscreen = false;
|
||||
private Pane mPane = Pane.MAP;
|
||||
private String mHighlighter = null;
|
||||
|
||||
@ -141,8 +140,9 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
}
|
||||
|
||||
private void showNotice(final int which) {
|
||||
if ((mPrefs.getInt("pref_messages", 0) & which) != 0)
|
||||
if ((mPrefs.getInt("pref_messages", 0) & which) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String text;
|
||||
switch (which) {
|
||||
@ -187,8 +187,9 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
|
||||
private void updateActionBar() {
|
||||
int position = mNavigationAdapter.getPosition(mPane);
|
||||
if (position >= 0 && position < mNavigationAdapter.getCount())
|
||||
if (position >= 0 && position < mNavigationAdapter.getCount()) {
|
||||
mDrawerLeft.setItemChecked(position, true);
|
||||
}
|
||||
|
||||
if (mDesktopMode) {
|
||||
mActionBar.setDisplayHomeAsUpEnabled(false); // Hide "up" indicator
|
||||
@ -208,36 +209,33 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
mActionBar.setHomeButtonEnabled(true);// Make icon clickable
|
||||
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
|
||||
|
||||
if (mPane == Pane.MAP || mDrawerLayout.isDrawerOpen(mDrawerLeft))
|
||||
if (mPane == Pane.MAP || mDrawerLayout.isDrawerOpen(mDrawerLeft)) {
|
||||
setDrawerIndicatorEnabled(true);
|
||||
else
|
||||
} else {
|
||||
setDrawerIndicatorEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (mDrawerLayout.isDrawerOpen(mDrawerLeft))
|
||||
if (mDrawerLayout.isDrawerOpen(mDrawerLeft)) {
|
||||
mActionBar.setTitle(mIitc.getString(R.string.app_name));
|
||||
else
|
||||
} else {
|
||||
mActionBar.setTitle(getPaneTitle(mPane));
|
||||
}
|
||||
}
|
||||
|
||||
boolean mapVisible = mDesktopMode || mPane == Pane.MAP;
|
||||
if ("No Highlights".equals(mHighlighter) || isDrawerOpened() || mIsLoading || !mapVisible)
|
||||
if ("No Highlights".equals(mHighlighter) || isDrawerOpened() || mIsLoading || !mapVisible) {
|
||||
mActionBar.setSubtitle(null);
|
||||
else
|
||||
} else {
|
||||
mActionBar.setSubtitle(mHighlighter);
|
||||
|
||||
if (mFullscreen && mHideInFullscreen)
|
||||
mActionBar.hide();
|
||||
else
|
||||
mActionBar.show();
|
||||
}
|
||||
}
|
||||
|
||||
public void closeDrawers() {
|
||||
mDrawerLayout.closeDrawers();
|
||||
}
|
||||
|
||||
public String getPaneTitle(Pane pane)
|
||||
{
|
||||
public String getPaneTitle(Pane pane) {
|
||||
switch (pane) {
|
||||
case INFO:
|
||||
return "Info";
|
||||
@ -256,10 +254,6 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hideInFullscreen() {
|
||||
return mHideInFullscreen;
|
||||
}
|
||||
|
||||
public boolean isDrawerOpened() {
|
||||
return mDrawerLayout.isDrawerOpen(mDrawerLeft) || mDrawerLayout.isDrawerOpen(mDrawerRight);
|
||||
}
|
||||
@ -268,6 +262,7 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
public void onDrawerClosed(View drawerView) {
|
||||
super.onDrawerClosed(drawerView);
|
||||
|
||||
mIitc.getWebView().onWindowFocusChanged(true);
|
||||
// delay invalidating to prevent flickering in case another drawer is opened
|
||||
(new Handler()).postDelayed(new Runnable() {
|
||||
@Override
|
||||
@ -281,6 +276,7 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
@Override
|
||||
public void onDrawerOpened(View drawerView) {
|
||||
super.onDrawerOpened(drawerView);
|
||||
mIitc.getWebView().onWindowFocusChanged(false);
|
||||
mIitc.invalidateOptionsMenu();
|
||||
updateActionBar();
|
||||
mDrawerLayout.closeDrawer(drawerView.equals(mDrawerLeft) ? mDrawerRight : mDrawerLeft);
|
||||
@ -291,16 +287,18 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
Pane item = mNavigationAdapter.getItem(position);
|
||||
mIitc.switchToPane(item);
|
||||
|
||||
if (item == Pane.INFO)
|
||||
if (item == Pane.INFO) {
|
||||
showNotice(NOTICE_INFO);
|
||||
}
|
||||
|
||||
mDrawerLayout.closeDrawer(mDrawerLeft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home)
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
mDrawerLayout.closeDrawer(mDrawerRight);
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@ -312,13 +310,13 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
|
||||
public void onPrefChanged() {
|
||||
mDesktopMode = mPrefs.getBoolean("pref_force_desktop", false);
|
||||
mHideInFullscreen = mPrefs.getBoolean("pref_fullscreen_actionbar", true);
|
||||
updateActionBar();
|
||||
}
|
||||
|
||||
public void openRightDrawer() {
|
||||
if (mDrawerLayout.getDrawerLockMode(mDrawerRight) == DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||
if (mDrawerLayout.getDrawerLockMode(mDrawerRight) == DrawerLayout.LOCK_MODE_UNLOCKED) {
|
||||
mDrawerLayout.openDrawer(mDrawerRight);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
@ -328,18 +326,9 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
|
||||
public void setDebugMode(boolean enabled) {
|
||||
mNavigationAdapter.remove(Pane.DEBUG); // avoid duplicates
|
||||
if (enabled)
|
||||
if (enabled) {
|
||||
mNavigationAdapter.add(Pane.DEBUG);
|
||||
}
|
||||
|
||||
public void setFullscreen(boolean fullscreen) {
|
||||
mFullscreen = fullscreen;
|
||||
if (mFullscreen && mHideInFullscreen) {
|
||||
// show a toast with instructions to exit the fullscreen mode again
|
||||
Toast.makeText(mIitc, "Press back button to exit fullscreen", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
updateActionBar();
|
||||
}
|
||||
|
||||
public void setHighlighter(String name) {
|
||||
@ -357,4 +346,12 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt
|
||||
|
||||
updateActionBar();
|
||||
}
|
||||
|
||||
public void showActionBar() {
|
||||
mActionBar.show();
|
||||
}
|
||||
|
||||
public void hideActionBar() {
|
||||
mActionBar.hide();
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
@ -62,8 +63,10 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
if(onIsMultiPane()) getIntent()
|
||||
.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, PluginsFragment.class.getName());
|
||||
if (onIsMultiPane()) {
|
||||
getIntent()
|
||||
.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, PluginsFragment.class.getName());
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@ -76,7 +79,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
|
||||
// Select the displayed fragment in the headers (when using a tablet) :
|
||||
// This should be done by Android, it is a bug fix
|
||||
// thx to http://stackoverflow.com/a/16793839
|
||||
if(mHeaders != null) {
|
||||
if (mHeaders != null) {
|
||||
|
||||
final String displayedFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
|
||||
if (displayedFragment != null) {
|
||||
@ -162,8 +165,9 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
|
||||
// TODO Auto-generated catch block
|
||||
e2.printStackTrace();
|
||||
}
|
||||
if (s != null)
|
||||
if (s != null) {
|
||||
src = s.hasNext() ? s.next() : "";
|
||||
}
|
||||
// now we have all stuff together and can build the pref screen
|
||||
addPluginPreference(src, anAsset_array, false);
|
||||
}
|
||||
@ -179,8 +183,9 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
|
||||
e.printStackTrace();
|
||||
Log.d("iitcm", "failed to parse file " + file);
|
||||
}
|
||||
if (s != null)
|
||||
if (s != null) {
|
||||
src = s.hasNext() ? s.next() : "";
|
||||
}
|
||||
|
||||
// now we have all stuff together and can build the pref screen
|
||||
addPluginPreference(src, file.toString(), true);
|
||||
@ -189,26 +194,12 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
|
||||
|
||||
void addPluginPreference(String src, String plugin_key, boolean user) {
|
||||
|
||||
// now parse plugin name, description and category
|
||||
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";
|
||||
String plugin_desc = "not found";
|
||||
String plugin_cat = "Misc";
|
||||
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("@description"))
|
||||
plugin_desc = attributes[j + 1];
|
||||
if (attributes[j].equals("@category"))
|
||||
plugin_cat = attributes[j + 1];
|
||||
}
|
||||
// parse plugin name, description and category
|
||||
// we need default versions here otherwise iitcm may crash
|
||||
HashMap<String,String> info = IITC_WebViewClient.getScriptInfo(src);
|
||||
String plugin_name = info.get("name");
|
||||
String plugin_cat = info.get("category");
|
||||
String plugin_desc = info.get("description");
|
||||
|
||||
// remove IITC plugin prefix from plugin_name
|
||||
plugin_name = plugin_name.replace("IITC Plugin: ", "");
|
||||
@ -227,7 +218,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
|
||||
|
||||
// now we have all stuff together and can build the preference
|
||||
// first check if we need a new category
|
||||
if (sPlugins.containsKey(plugin_cat) == false) {
|
||||
if (!sPlugins.containsKey(plugin_cat)) {
|
||||
sPlugins.put(plugin_cat, new ArrayList<IITC_PluginPreference>());
|
||||
Log.d("iitcm", "create " + plugin_cat + " and add " + plugin_name);
|
||||
}
|
||||
@ -288,7 +279,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
|
||||
TextView summary;
|
||||
}
|
||||
|
||||
private LayoutInflater mInflater;
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
static int getHeaderType(Header header) {
|
||||
if (header.fragment == null && header.intent == null) {
|
||||
|
@ -15,6 +15,7 @@ public class IITC_PreferenceActivity extends Activity {
|
||||
MainSettings settings = new MainSettings();
|
||||
|
||||
getActionBar().setHomeButtonEnabled(true);
|
||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// iitc version
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
|
@ -11,41 +11,71 @@ import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.ConsoleMessage;
|
||||
import android.webkit.GeolocationPermissions;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.cradle.iitc_mobile.async.CheckHttpResponse;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
public class IITC_WebView extends WebView {
|
||||
|
||||
// fullscreen modes
|
||||
public static final int FS_ENABLED = (1 << 0);
|
||||
public static final int FS_SYSBAR = (1 << 1);
|
||||
public static final int FS_ACTIONBAR = (1 << 2);
|
||||
public static final int FS_STATUSBAR = (1 << 3);
|
||||
public static final int FS_NAVBAR = (1 << 4);
|
||||
|
||||
private WebSettings mSettings;
|
||||
private IITC_WebViewClient mIitcWebViewClient;
|
||||
private IITC_JSInterface mJsInterface;
|
||||
private Context mContext;
|
||||
private IITC_Mobile mIitc;
|
||||
private SharedPreferences mSharedPrefs;
|
||||
private int mFullscreenStatus = 0;
|
||||
private Runnable mNavHider;
|
||||
private boolean mDisableJs = false;
|
||||
private String mDefaultUserAgent;
|
||||
private final String mDesktopUserAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:17.0)" +
|
||||
" Gecko/20130810 Firefox/17.0 Iceweasel/17.0.8";
|
||||
|
||||
// init web view
|
||||
private void iitc_init(Context c) {
|
||||
if (this.isInEditMode()) return;
|
||||
mContext = c;
|
||||
mSettings = this.getSettings();
|
||||
if (isInEditMode()) return;
|
||||
mIitc = (IITC_Mobile) c;
|
||||
mSettings = getSettings();
|
||||
mSettings.setJavaScriptEnabled(true);
|
||||
mSettings.setDomStorageEnabled(true);
|
||||
mSettings.setAllowFileAccess(true);
|
||||
mSettings.setGeolocationEnabled(true);
|
||||
mSettings.setAppCacheEnabled(true);
|
||||
mSettings.setDatabasePath(this.getContext().getApplicationInfo().dataDir
|
||||
+ "/databases/");
|
||||
mSettings.setAppCachePath(this.getContext().getCacheDir()
|
||||
.getAbsolutePath());
|
||||
this.mJsInterface = new IITC_JSInterface((IITC_Mobile) mContext);
|
||||
this.addJavascriptInterface(mJsInterface, "android");
|
||||
mSettings.setDatabasePath(getContext().getApplicationInfo().dataDir + "/databases/");
|
||||
mSettings.setAppCachePath(getContext().getCacheDir().getAbsolutePath());
|
||||
mJsInterface = new IITC_JSInterface(mIitc);
|
||||
addJavascriptInterface(mJsInterface, "android");
|
||||
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(mIitc);
|
||||
mDefaultUserAgent = mSettings.getUserAgentString();
|
||||
setUserAgent();
|
||||
|
||||
this.setWebChromeClient(new WebChromeClient() {
|
||||
mNavHider = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isInFullscreen() && (getFullscreenStatus() & (FS_NAVBAR)) != 0) {
|
||||
setSystemUiVisibility(SYSTEM_UI_FLAG_HIDE_NAVIGATION);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
setWebChromeClient(new WebChromeClient() {
|
||||
/**
|
||||
* our webchromeclient should share geolocation with the iitc script
|
||||
*
|
||||
@ -53,7 +83,7 @@ public class IITC_WebView extends WebView {
|
||||
*/
|
||||
@Override
|
||||
public void onGeolocationPermissionsShowPrompt(String origin,
|
||||
GeolocationPermissions.Callback callback) {
|
||||
GeolocationPermissions.Callback callback) {
|
||||
callback.invoke(origin, true, false);
|
||||
}
|
||||
|
||||
@ -75,15 +105,14 @@ public class IITC_WebView extends WebView {
|
||||
@Override
|
||||
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
|
||||
if (consoleMessage.messageLevel() == ConsoleMessage.MessageLevel.ERROR) {
|
||||
Log.d("iitcm", consoleMessage.message());
|
||||
((IITC_Mobile) getContext()).setLoadingState(false);
|
||||
mIitc.setLoadingState(false);
|
||||
}
|
||||
return super.onConsoleMessage(consoleMessage);
|
||||
}
|
||||
});
|
||||
|
||||
mIitcWebViewClient = new IITC_WebViewClient(c);
|
||||
this.setWebViewClient(mIitcWebViewClient);
|
||||
setWebViewClient(mIitcWebViewClient);
|
||||
}
|
||||
|
||||
// constructors -------------------------------------------------
|
||||
@ -110,7 +139,7 @@ public class IITC_WebView extends WebView {
|
||||
@Override
|
||||
public void loadUrl(String url) {
|
||||
// if in edit text mode, don't load javascript otherwise the keyboard closes.
|
||||
HitTestResult testResult = this.getHitTestResult();
|
||||
HitTestResult testResult = getHitTestResult();
|
||||
if (url.startsWith("javascript:") && testResult != null &&
|
||||
testResult.getType() == HitTestResult.EDIT_TEXT_TYPE) {
|
||||
// let window.show(...) interupt input
|
||||
@ -122,7 +151,7 @@ public class IITC_WebView extends WebView {
|
||||
}
|
||||
}
|
||||
// do nothing if script is enabled;
|
||||
if (this.mDisableJs) {
|
||||
if (mDisableJs) {
|
||||
Log.d("iitcm", "javascript injection disabled...return");
|
||||
return;
|
||||
}
|
||||
@ -130,39 +159,124 @@ public class IITC_WebView extends WebView {
|
||||
// force https if enabled in settings
|
||||
SharedPreferences sharedPref = PreferenceManager
|
||||
.getDefaultSharedPreferences(getContext());
|
||||
if (sharedPref.getBoolean("pref_force_https", true))
|
||||
if (sharedPref.getBoolean("pref_force_https", true)) {
|
||||
url = url.replace("http://", "https://");
|
||||
else
|
||||
} else {
|
||||
url = url.replace("https://", "http://");
|
||||
}
|
||||
|
||||
// disable splash screen if a http error code is responded
|
||||
new CheckHttpResponse(mJsInterface, mContext).execute(url);
|
||||
new CheckHttpResponse(mJsInterface, mIitc).execute(url);
|
||||
Log.d("iitcm", "loading url: " + url);
|
||||
}
|
||||
super.loadUrl(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
getHandler().removeCallbacks(mNavHider);
|
||||
getHandler().postDelayed(mNavHider, 2000);
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemUiVisibility(int visibility) {
|
||||
getHandler().postDelayed(mNavHider, 2000);
|
||||
super.setSystemUiVisibility(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
||||
if (hasWindowFocus) {
|
||||
getHandler().postDelayed(mNavHider, 2000);
|
||||
} else {
|
||||
getHandler().removeCallbacks(mNavHider);
|
||||
}
|
||||
super.onWindowFocusChanged(hasWindowFocus);
|
||||
}
|
||||
|
||||
public void toggleFullscreen() {
|
||||
mFullscreenStatus ^= FS_ENABLED;
|
||||
|
||||
WindowManager.LayoutParams attrs = mIitc.getWindow().getAttributes();
|
||||
// toggle notification bar
|
||||
if (isInFullscreen()) {
|
||||
// show a toast with instructions to exit the fullscreen mode again
|
||||
Toast.makeText(mIitc, "Press back button to exit fullscreen", Toast.LENGTH_SHORT).show();
|
||||
if ((mFullscreenStatus & FS_ACTIONBAR) != 0) {
|
||||
mIitc.getNavigationHelper().hideActionBar();
|
||||
}
|
||||
if ((mFullscreenStatus & FS_SYSBAR) != 0) {
|
||||
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
}
|
||||
if ((mFullscreenStatus & FS_NAVBAR) != 0) {
|
||||
setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
|
||||
}
|
||||
if ((mFullscreenStatus & FS_STATUSBAR) != 0) {
|
||||
loadUrl("javascript: $('#updatestatus').hide();");
|
||||
}
|
||||
} else {
|
||||
attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
mIitc.getNavigationHelper().showActionBar();
|
||||
loadUrl("javascript: $('#updatestatus').show();");
|
||||
}
|
||||
mIitc.getWindow().setAttributes(attrs);
|
||||
}
|
||||
|
||||
void updateFullscreenStatus() {
|
||||
Set<String> entries = mSharedPrefs.getStringSet("pref_fullscreen", new HashSet<String>());
|
||||
mFullscreenStatus &= FS_ENABLED;
|
||||
|
||||
// default values...android has no nice way to add default values to multiSelectListPreferences
|
||||
if (entries.isEmpty()) {
|
||||
mFullscreenStatus += FS_ACTIONBAR | FS_SYSBAR;
|
||||
}
|
||||
for (String entry : entries) {
|
||||
mFullscreenStatus += Integer.parseInt(entry);
|
||||
}
|
||||
}
|
||||
|
||||
int getFullscreenStatus() {
|
||||
return mFullscreenStatus;
|
||||
}
|
||||
|
||||
public boolean isInFullscreen() {
|
||||
return (mFullscreenStatus & FS_ENABLED) != 0;
|
||||
}
|
||||
|
||||
public IITC_WebViewClient getWebViewClient() {
|
||||
return this.mIitcWebViewClient;
|
||||
return mIitcWebViewClient;
|
||||
}
|
||||
|
||||
public IITC_JSInterface getJSInterface() {
|
||||
return this.mJsInterface;
|
||||
return mJsInterface;
|
||||
}
|
||||
|
||||
public void updateCaching() {
|
||||
boolean login = false;
|
||||
if (getUrl() != null) {
|
||||
login = getUrl().contains("accounts.google.com");
|
||||
}
|
||||
// use cache if on mobile network...saves traffic
|
||||
if (!this.isConnectedToWifi() && !login) {
|
||||
Log.d("iitcm", "not connected to wifi...load tiles from cache");
|
||||
mSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
|
||||
} else {
|
||||
if (login) Log.d("iitcm", "login...load tiles from network");
|
||||
else Log.d("iitcm", "connected to wifi...load tiles from network");
|
||||
mSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
public void updateCaching(boolean login) {
|
||||
switch (Integer.parseInt(mSharedPrefs.getString("pref_caching", "1"))) {
|
||||
case 0:
|
||||
mSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
|
||||
break;
|
||||
case 2:
|
||||
mSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
break;
|
||||
default:
|
||||
if (getUrl() != null) {
|
||||
login |= getUrl().contains("accounts.google.com");
|
||||
}
|
||||
// use cache if on mobile network...saves traffic
|
||||
if (!isConnectedToWifi() && !login) {
|
||||
Log.d("iitcm", "not connected to wifi...load tiles from cache");
|
||||
mSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
|
||||
} else {
|
||||
if (login) {
|
||||
Log.d("iitcm", "login...load tiles from network");
|
||||
} else {
|
||||
Log.d("iitcm", "connected to wifi...load tiles from network");
|
||||
}
|
||||
mSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +298,12 @@ public class IITC_WebView extends WebView {
|
||||
}
|
||||
|
||||
public void disableJS(boolean val) {
|
||||
this.mDisableJs = val;
|
||||
mDisableJs = val;
|
||||
}
|
||||
|
||||
public void setUserAgent() {
|
||||
String ua = mSharedPrefs.getBoolean("pref_fake_user_agent", false) ? mDesktopUserAgent : mDefaultUserAgent;
|
||||
Log.d("iitcm", "setting user agent to: " + ua);
|
||||
mSettings.setUserAgentString(ua);
|
||||
}
|
||||
}
|
||||
|
@ -12,18 +12,21 @@ import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.cradle.iitc_mobile.async.UrlContentToString;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -49,21 +52,49 @@ public class IITC_WebViewClient extends WebViewClient {
|
||||
}
|
||||
|
||||
public String getIITCVersion() {
|
||||
HashMap<String, String> map = getScriptInfo(mIitcScript);
|
||||
return map.get("version");
|
||||
}
|
||||
|
||||
// static method because we use it in IITC_PluginPreferenceActivity too
|
||||
public static HashMap<String, String> getScriptInfo(String js) {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
String header = "";
|
||||
if (mIitcScript != null)
|
||||
header = mIitcScript.substring(mIitcScript.indexOf("==UserScript=="),
|
||||
mIitcScript.indexOf("==/UserScript=="));
|
||||
// remove new line comments
|
||||
header = header.replace("\n//", "");
|
||||
// get a list of key-value
|
||||
String[] attributes = header.split(" +");
|
||||
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 (js != null) {
|
||||
header = js.substring(js.indexOf("==UserScript=="),
|
||||
js.indexOf("==/UserScript=="));
|
||||
}
|
||||
return iitc_version;
|
||||
// remove new line comments
|
||||
header = header.replace("\n//", " ");
|
||||
// get a list of key-value
|
||||
String[] attributes = header.split(" +");
|
||||
// add default values
|
||||
map.put("version", "not found");
|
||||
map.put("name", "unknown");
|
||||
map.put("description", "");
|
||||
map.put("category", "Misc");
|
||||
// add parsed values
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
// search for attributes and use the value
|
||||
if (attributes[i].equals("@version")) {
|
||||
map.put("version", attributes[i + 1]);
|
||||
}
|
||||
if (attributes[i].equals("@name")) {
|
||||
map.put("name", attributes[i + 1]);
|
||||
}
|
||||
if (attributes[i].equals("@description")) {
|
||||
map.put("description", attributes[i + 1]);
|
||||
}
|
||||
if (attributes[i].equals("@category")) {
|
||||
map.put("category", attributes[i + 1]);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public String getGmInfoJson(HashMap<String, String> map) {
|
||||
JSONObject jObject = new JSONObject(map);
|
||||
return "{\"script\":" + jObject.toString() + "}";
|
||||
}
|
||||
|
||||
public void loadIITC_JS(Context c) throws java.io.IOException {
|
||||
@ -129,12 +160,9 @@ public class IITC_WebViewClient extends WebViewClient {
|
||||
js = js.replace("window.showLayerChooser = true;",
|
||||
"window.showLayerChooser = false");
|
||||
}
|
||||
// add all plugins to the script...inject plugins + main script simultaneously
|
||||
js += parsePlugins();
|
||||
|
||||
// IITC expects to be injected after the DOM has been loaded completely.
|
||||
// since it is injected with the onPageFinished() event, no further delay is necessary.
|
||||
this.mIitcScript = js;
|
||||
String gmInfo = "GM_info=" + getGmInfoJson(getScriptInfo(js)).toString() + "\n";
|
||||
this.mIitcScript = gmInfo + js;
|
||||
|
||||
}
|
||||
|
||||
@ -148,9 +176,10 @@ public class IITC_WebViewClient extends WebViewClient {
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
if (url.startsWith("http://www.ingress.com/intel")
|
||||
|| url.startsWith("https://www.ingress.com/intel")) {
|
||||
|| url.startsWith("https://www.ingress.com/intel")) {
|
||||
Log.d("iitcm", "injecting iitc..");
|
||||
view.loadUrl("javascript: " + this.mIitcScript);
|
||||
loadPlugins(view);
|
||||
}
|
||||
super.onPageFinished(view, url);
|
||||
}
|
||||
@ -161,17 +190,17 @@ public class IITC_WebViewClient extends WebViewClient {
|
||||
@Override
|
||||
public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
|
||||
Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args);
|
||||
((IITC_Mobile) mContext).onReceivedLoginRequest(this, view, realm, account, args);
|
||||
Log.d("iitcm", "logging in...updating caching mode");
|
||||
((IITC_WebView) view).updateCaching(true);
|
||||
//((IITC_Mobile) mContext).onReceivedLoginRequest(this, view, realm, account, args);
|
||||
}
|
||||
|
||||
// parse all enabled iitc plugins
|
||||
// returns a string containing all plugins without their wrappers
|
||||
public String parsePlugins() {
|
||||
String js = "";
|
||||
public void loadPlugins(WebView view) {
|
||||
// get the plugin preferences
|
||||
SharedPreferences sharedPref = PreferenceManager
|
||||
.getDefaultSharedPreferences(mContext);
|
||||
boolean dev_enabled = sharedPref.getBoolean("pref_dev_checkbox", false);
|
||||
String path = (dev_enabled) ? mIitcPath + "dev/plugins/" : "plugins/";
|
||||
|
||||
Map<String, ?> all_prefs = sharedPref.getAll();
|
||||
|
||||
@ -179,39 +208,36 @@ public class IITC_WebViewClient extends WebViewClient {
|
||||
for (Map.Entry<String, ?> entry : all_prefs.entrySet()) {
|
||||
String plugin = entry.getKey();
|
||||
if (plugin.endsWith("user.js") && entry.getValue().toString().equals("true")) {
|
||||
// load default iitc plugins
|
||||
if (!plugin.startsWith(mIitcPath)) {
|
||||
// load default iitc plugins
|
||||
Log.d("iitcm", "adding plugin " + plugin);
|
||||
if (dev_enabled)
|
||||
js += this.removePluginWrapper(mIitcPath + "dev/plugins/"
|
||||
+ plugin, false);
|
||||
else
|
||||
js += this.removePluginWrapper("plugins/" + plugin, true);
|
||||
// load user iitc plugins
|
||||
loadJS(path + plugin, !dev_enabled, view);
|
||||
} else {
|
||||
// load user iitc plugins
|
||||
Log.d("iitcm", "adding user plugin " + plugin);
|
||||
js += this.removePluginWrapper(plugin, false);
|
||||
loadJS(plugin, false, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// inject the user location script if enabled in settings
|
||||
if (sharedPref.getBoolean("pref_user_loc", false))
|
||||
js += parseTrackingPlugin(dev_enabled);
|
||||
|
||||
return js;
|
||||
if (sharedPref.getBoolean("pref_user_loc", false)) {
|
||||
path = path.replace("plugins/", "");
|
||||
loadJS(path + "user-location.user.js", !dev_enabled, view);
|
||||
}
|
||||
}
|
||||
|
||||
public String parseTrackingPlugin(boolean dev_enabled) {
|
||||
Log.d("iitcm", "enable tracking...");
|
||||
String js = "";
|
||||
// load plugin from external storage if dev mode are enabled
|
||||
if (dev_enabled)
|
||||
js = this.removePluginWrapper(mIitcPath + "dev/user-location.user.js", false);
|
||||
else
|
||||
// load plugin from asset folder
|
||||
js = this.removePluginWrapper("user-location.user.js", true);
|
||||
return js;
|
||||
// read a file into a string
|
||||
// load it as javascript
|
||||
public boolean loadJS(String file, boolean asset, WebView view) {
|
||||
String js = fileToString(file, asset);
|
||||
if (js.equals("false")) {
|
||||
return false;
|
||||
} else {
|
||||
String gmInfo = "GM_info=" + getGmInfoJson(getScriptInfo(js)) + "\n";
|
||||
view.loadUrl("javascript:" + gmInfo + js);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// read a file into a string
|
||||
@ -241,51 +267,10 @@ public class IITC_WebViewClient extends WebViewClient {
|
||||
}
|
||||
}
|
||||
|
||||
if (s != null)
|
||||
if (s != null) {
|
||||
src = s.hasNext() ? s.next() : "";
|
||||
return src;
|
||||
}
|
||||
|
||||
// read a file into a string
|
||||
// load it as javascript
|
||||
// at the moment not needed, but not bad to have it in the IITC_WebViewClient API
|
||||
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;
|
||||
}
|
||||
|
||||
// iitc and all plugins are loaded at the same time
|
||||
// so remove the wrapper functions and injection code
|
||||
// TODO: it only works if the plugin is coded with the iitc plugin template
|
||||
public String removePluginWrapper(String file, boolean asset) {
|
||||
if (!file.endsWith("user.js")) return "";
|
||||
String js = fileToString(file, asset);
|
||||
if (js.equals("false")) return "";
|
||||
js = js.replaceAll("\r\n", "\n"); //convert CR-LF pairs to LF - windows format text files
|
||||
js = js.replaceAll("\r", "\n"); //convert remaining CR to LF - Mac format files(?)
|
||||
String wrapper_start = "function wrapper() {";
|
||||
String wrapper_end = "} // wrapper end";
|
||||
String injection_code = "// inject code into site context\n" +
|
||||
"var script = document.createElement('script');\n" +
|
||||
"script.appendChild(document.createTextNode('('+ wrapper +')();'));\n" +
|
||||
"(document.body || document.head || document.documentElement).appendChild(script);";
|
||||
if (js.contains(wrapper_start) && js.contains(wrapper_end) && js.contains(injection_code)) {
|
||||
js = js.replace(wrapper_start, "");
|
||||
// remove the wrapper function
|
||||
js = js.replace(wrapper_end, "");
|
||||
// and the code injection
|
||||
js = js.replace(injection_code, "");
|
||||
} else {
|
||||
Log.d("iitcm", "Removal of wrapper/injection code failed for " + file);
|
||||
return "";
|
||||
}
|
||||
return js;
|
||||
return src;
|
||||
}
|
||||
|
||||
// Check every external resource if it’s okay to load it and maybe replace
|
||||
@ -332,8 +317,8 @@ public class IITC_WebViewClient extends WebViewClient {
|
||||
((IITC_Mobile) mContext).loadUrl(url);
|
||||
}
|
||||
if (url.contains("logout")) {
|
||||
Log.d("iitcm", "logging out...set caching mode to default");
|
||||
view.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||
Log.d("iitcm", "logging out...updating caching mode");
|
||||
((IITC_WebView) view).updateCaching(true);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
|
@ -24,13 +24,13 @@ import java.io.IOException;
|
||||
*/
|
||||
public class CheckHttpResponse extends AsyncTask<String, Void, Boolean> {
|
||||
|
||||
private IITC_JSInterface mJsInterface;
|
||||
private Context mContext;
|
||||
private final IITC_JSInterface mJsInterface;
|
||||
private final Context mContext;
|
||||
|
||||
public CheckHttpResponse(IITC_JSInterface jsInterface, Context c) {
|
||||
mContext = c;
|
||||
mJsInterface = jsInterface;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... urls) {
|
||||
|
@ -1,63 +1,111 @@
|
||||
package com.cradle.iitc_mobile.fragments;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.cradle.iitc_mobile.IITC_AboutDialogPreference;
|
||||
import com.cradle.iitc_mobile.R;
|
||||
|
||||
public class MainSettings extends PreferenceFragment {
|
||||
|
||||
private String mIitcVersion;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mIitcVersion = getArguments().getString("iitc_version");
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
// set build version
|
||||
ListPreference pref_build_version = (ListPreference) findPreference("pref_build_version");
|
||||
// set versions
|
||||
String iitcVersion = getArguments().getString("iitc_version");
|
||||
String buildVersion = "unknown";
|
||||
|
||||
PackageManager pm = getActivity().getPackageManager();
|
||||
String version = "unknown";
|
||||
try {
|
||||
PackageInfo info = pm.getPackageInfo(
|
||||
getActivity().getPackageName(), 0);
|
||||
version = info.versionName;
|
||||
PackageInfo info = pm.getPackageInfo(getActivity().getPackageName(), 0);
|
||||
buildVersion = info.versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
pref_build_version.setSummary(version);
|
||||
|
||||
// set iitc version
|
||||
ListPreference pref_iitc_version = (ListPreference) findPreference("pref_iitc_version");
|
||||
pref_iitc_version.setSummary(mIitcVersion);
|
||||
IITC_AboutDialogPreference pref_about = (IITC_AboutDialogPreference) findPreference("pref_about");
|
||||
pref_about.setVersions(iitcVersion, buildVersion);
|
||||
|
||||
// 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(getString(R.string.pref_select_iitc_sum) +
|
||||
" " + newValue);
|
||||
// TODO: update mIitcVersion when iitc source has
|
||||
// changed
|
||||
return true;
|
||||
}
|
||||
});
|
||||
pref_iitc_source.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
preference.setSummary(getString(R.string.pref_select_iitc_sum) + " " + newValue);
|
||||
// TODO: update mIitcVersion when iitc source has changed
|
||||
return true;
|
||||
}
|
||||
});
|
||||
// first init of summary
|
||||
String pref_iitc_source_sum = getString(R.string.pref_select_iitc_sum)
|
||||
+ " " + pref_iitc_source.getText();
|
||||
String pref_iitc_source_sum = getString(R.string.pref_select_iitc_sum) + " " + pref_iitc_source.getText();
|
||||
pref_iitc_source.setSummary(pref_iitc_source_sum);
|
||||
}
|
||||
|
||||
// we want a home button + HomeAsUpEnabled in nested preferences
|
||||
// for some odd reasons android is not able to do this by default
|
||||
// so we need some additional hacks...
|
||||
// thx to http://stackoverflow.com/a/16800527/2638486 !!
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
if (preference.getTitle().toString().equals(getString(R.string.pref_advanced_options))
|
||||
|| preference.getTitle().toString().equals(getString(R.string.pref_about_title))) {
|
||||
initializeActionBar((PreferenceScreen) preference);
|
||||
}
|
||||
return super.onPreferenceTreeClick(preferenceScreen, preference);
|
||||
}
|
||||
|
||||
// Apply custom home button area click listener to close the PreferenceScreen
|
||||
// because PreferenceScreens are dialogs which swallow
|
||||
// events instead of passing to the activity
|
||||
// Related Issue: https://code.google.com/p/android/issues/detail?id=4611
|
||||
public static void initializeActionBar(PreferenceScreen preferenceScreen) {
|
||||
final Dialog dialog = preferenceScreen.getDialog();
|
||||
|
||||
if (dialog != null) {
|
||||
dialog.getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
View homeBtn = dialog.findViewById(android.R.id.home);
|
||||
|
||||
if (homeBtn != null) {
|
||||
View.OnClickListener dismissDialogClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
};
|
||||
|
||||
ViewParent homeBtnContainer = homeBtn.getParent();
|
||||
|
||||
// The home button is an ImageView inside a FrameLayout
|
||||
if (homeBtnContainer instanceof FrameLayout) {
|
||||
ViewGroup containerParent = (ViewGroup) homeBtnContainer.getParent();
|
||||
|
||||
if (containerParent instanceof LinearLayout) {
|
||||
// This view also contains the title text, set the whole view as clickable
|
||||
((LinearLayout) containerParent).setOnClickListener(dismissDialogClickListener);
|
||||
} else {
|
||||
// Just set it on the home button
|
||||
((FrameLayout) homeBtnContainer).setOnClickListener(dismissDialogClickListener);
|
||||
}
|
||||
} else {
|
||||
homeBtn.setOnClickListener(dismissDialogClickListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,9 @@ public class IntentFragment extends Fragment implements OnScrollListener, OnItem
|
||||
mIntents = args.getParcelableArrayList("intents");
|
||||
mListView = new IntentListView(getActivity());
|
||||
mListView.setIntents(mIntents);
|
||||
if (mScrollIndex != -1 && mScrollTop != -1)
|
||||
if (mScrollIndex != -1 && mScrollTop != -1) {
|
||||
mListView.setSelectionFromTop(mScrollIndex, mScrollTop);
|
||||
}
|
||||
mListView.setOnScrollListener(this);
|
||||
mListView.setOnItemClickListener(this);
|
||||
|
||||
|
@ -8,7 +8,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IntentFragmentAdapter extends FragmentPagerAdapter {
|
||||
private List<IntentFragment> mTabs;
|
||||
private final List<IntentFragment> mTabs;
|
||||
|
||||
public IntentFragmentAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
|
@ -60,8 +60,9 @@ public class IntentListView extends ListView {
|
||||
private static final HashSet<CopyHandler> KNOWN_COPY_HANDLERS = new HashSet<CopyHandler>();
|
||||
|
||||
private static void setupKnownCopyHandlers() {
|
||||
if (!KNOWN_COPY_HANDLERS.isEmpty())
|
||||
if (!KNOWN_COPY_HANDLERS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
KNOWN_COPY_HANDLERS.add(new CopyHandler(
|
||||
"com.google.android.apps.docs",
|
||||
@ -74,7 +75,7 @@ public class IntentListView extends ListView {
|
||||
|
||||
private IntentAdapter mAdapter;
|
||||
private PackageManager mPackageManager;
|
||||
HashMap<ComponentName, Intent> mActivities = new HashMap<ComponentName, Intent>();
|
||||
private final HashMap<ComponentName, Intent> mActivities = new HashMap<ComponentName, Intent>();
|
||||
|
||||
public IntentListView(Context context) {
|
||||
super(context);
|
||||
@ -141,8 +142,9 @@ public class IntentListView extends ListView {
|
||||
for (ResolveInfo resolveInfo : activityList) { // search for "Copy to clipboard" handler
|
||||
CopyHandler handler = new CopyHandler(resolveInfo);
|
||||
|
||||
if (KNOWN_COPY_HANDLERS.contains(handler))
|
||||
if (KNOWN_COPY_HANDLERS.contains(handler)) {
|
||||
hasCopyIntent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// use traditional loop since list may change during iteration
|
||||
@ -155,7 +157,6 @@ public class IntentListView extends ListView {
|
||||
if (hasCopyIntent || !activity.name.equals(SendToClipboard.class.getCanonicalName())) {
|
||||
activityList.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,8 +173,7 @@ public class IntentListView extends ListView {
|
||||
if (resolveInfo.activityInfo.packageName.equals(defaultTarget.activityInfo.packageName)
|
||||
&& resolveInfo.activityInfo.name.equals(defaultTarget.activityInfo.name)) {
|
||||
allActivities.add(0, resolveInfo);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
allActivities.add(resolveInfo);
|
||||
}
|
||||
}
|
||||
|
@ -45,15 +45,17 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList
|
||||
|
||||
private String getUrl() {
|
||||
String url = "http://www.ingress.com/intel?ll=" + mLl + "&z=" + mZoom;
|
||||
if (mIsPortal)
|
||||
if (mIsPortal) {
|
||||
url += "&pll=" + mLl;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
private void setSelected(int position) {
|
||||
// Activity not fully loaded yet (may occur during tab creation)
|
||||
if (mSharedPrefs == null)
|
||||
if (mSharedPrefs == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSharedPrefs
|
||||
.edit()
|
||||
@ -103,12 +105,11 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList
|
||||
mFragmentAdapter = new IntentFragmentAdapter(getSupportFragmentManager());
|
||||
|
||||
final ActionBar actionBar = getActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
Intent intent = getIntent();
|
||||
// from portallinks/permalinks we build 3 intents (share / geo / vanilla-intel-link)
|
||||
if (intent.getBooleanExtra("onlyShare", false) == false) {
|
||||
if (!intent.getBooleanExtra("onlyShare", false)) {
|
||||
mTitle = intent.getStringExtra("title");
|
||||
mLl = intent.getDoubleExtra("lat", 0) + "," + intent.getDoubleExtra("lng", 0);
|
||||
mZoom = intent.getIntExtra("zoom", 0);
|
||||
@ -126,7 +127,9 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList
|
||||
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
actionBar.setSelectedNavigationItem(position);
|
||||
if (actionBar.getNavigationMode() != ActionBar.NAVIGATION_MODE_STANDARD) {
|
||||
actionBar.setSelectedNavigationItem(position);
|
||||
}
|
||||
setSelected(position);
|
||||
}
|
||||
});
|
||||
@ -141,11 +144,17 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList
|
||||
.setTabListener(this));
|
||||
}
|
||||
|
||||
if (mFragmentAdapter.getCount() > 1) {
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
}
|
||||
|
||||
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
int selected = mSharedPrefs.getInt("pref_share_selected_tab", 0);
|
||||
if (selected < mFragmentAdapter.getCount()) {
|
||||
mViewPager.setCurrentItem(selected);
|
||||
actionBar.setSelectedNavigationItem(selected);
|
||||
if (actionBar.getNavigationMode() != ActionBar.NAVIGATION_MODE_STANDARD) {
|
||||
actionBar.setSelectedNavigationItem(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
68
plugins/add-kml.user.js
Executable file
68
plugins/add-kml.user.js
Executable file
@ -0,0 +1,68 @@
|
||||
// ==UserScript==
|
||||
// @id overlay-kml@danielatkins
|
||||
// @name IITC plugin: overlay KML
|
||||
// @category Info
|
||||
// @version 0.1.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Allows users to overlay their own KML / GPX files on top of IITC
|
||||
// @include https://www.ingress.com/intel*
|
||||
// @include http://www.ingress.com/intel*
|
||||
// @match https://www.ingress.com/intel*
|
||||
// @match http://www.ingress.com/intel*
|
||||
// @grant none
|
||||
// ==/UserScript==
|
||||
|
||||
@@PLUGINSTART@@
|
||||
|
||||
// PLUGIN START ////////////////////////////////////////////////////////
|
||||
|
||||
// use own namespace for plugin
|
||||
window.plugin.overlayKML = function() {};
|
||||
|
||||
window.plugin.overlayKML.loadExternals = function() {
|
||||
try { console.log('Loading leaflet.filelayer JS now'); } catch(e) {}
|
||||
@@INCLUDERAW:external/leaflet.filelayer.js@@
|
||||
try { console.log('done loading leaflet.filelayer JS'); } catch(e) {}
|
||||
|
||||
try { console.log('Loading KML JS now'); } catch(e) {}
|
||||
@@INCLUDERAW:external/KML.js@@
|
||||
try { console.log('done loading KML JS'); } catch(e) {}
|
||||
|
||||
try { console.log('Loading togeojson JS now'); } catch(e) {}
|
||||
@@INCLUDERAW:external/togeojson.js@@
|
||||
try { console.log('done loading togeojson JS'); } catch(e) {}
|
||||
|
||||
window.plugin.overlayKML.load();
|
||||
}
|
||||
|
||||
window.plugin.overlayKML.load = function() {
|
||||
// Provide popup window allow user to select KML to overlay
|
||||
|
||||
L.Icon.Default.imagePath = '@@INCLUDEIMAGE:images/marker-icon.png@@';
|
||||
var KMLIcon = L.icon({
|
||||
iconUrl: '@@INCLUDEIMAGE:images/marker-icon.png@@',
|
||||
|
||||
iconSize: [16, 24], // size of the icon
|
||||
iconAnchor: [8, 24], // point of the icon which will correspond to marker's location
|
||||
popupAnchor: [-3, 16] // point from which the popup should open relative to the iconAnchor
|
||||
});
|
||||
|
||||
L.Control.FileLayerLoad.LABEL = '<img src="@@INCLUDEIMAGE:images/open-folder-icon_sml.png@@" alt="Open" />';
|
||||
L.Control.fileLayerLoad({
|
||||
fitBounds: true,
|
||||
layerOptions: {
|
||||
pointToLayer: function (data, latlng) {
|
||||
return L.marker(latlng, {icon: KMLIcon});
|
||||
}},
|
||||
}).addTo(map);
|
||||
}
|
||||
|
||||
var setup = function() {
|
||||
window.plugin.overlayKML.loadExternals();
|
||||
}
|
||||
|
||||
// PLUGIN END //////////////////////////////////////////////////////////
|
||||
|
||||
@@PLUGINEND@@
|
@ -2,7 +2,7 @@
|
||||
// @id iitc-plugin-bookmarks@ZasoGD
|
||||
// @name IITC plugin: Bookmarks for maps and portals
|
||||
// @category Controls
|
||||
// @version 0.2.4.@@DATETIMEVERSION@@
|
||||
// @version 0.2.5.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
@ -18,35 +18,14 @@
|
||||
|
||||
// PLUGIN START ////////////////////////////////////////////////////////
|
||||
/***********************************************************************
|
||||
USEFUL FUNCTIONS:
|
||||
+ window.plugin.bookmarks.refreshBkmrks(): reloads the bookmarks into box;
|
||||
|
||||
HOOKS:
|
||||
+ pluginBkmrksEdit: fired when a bookmarks/folder is removed, added or sorted, also when a folder is opened/closed;
|
||||
+ pluginBkmrksOpenOpt: fired when the "Bookmarks Options" panel is opened (you can add new options);
|
||||
|
||||
CHANGELOG:
|
||||
v 0.2.1-0.2.2:
|
||||
+ auto-drawer minor bug fix;
|
||||
+ auto-drawer improved UI;
|
||||
+ auto-drawer improved UI on mobile;
|
||||
+ fixed hidden box problem (I hope): sometimes the box and the ribbon hidden;
|
||||
|
||||
v 0.2.0:
|
||||
+ code rewritten from scratch:
|
||||
++ more optimization;
|
||||
++ less animated effects;
|
||||
+ Sync;
|
||||
+ Hooks (for developer);
|
||||
+ Option panel:
|
||||
++ manual import/export/reset of the data;
|
||||
++ sharing of the data (only IITCm);
|
||||
++ storage/reset the box position (only desktop);
|
||||
+ Auto-drawer feature: select two o three portals boomark to auto-draw a link or field (draw-tools required);
|
||||
+ IITCm: you can open/close the folders;
|
||||
+ IITCm: bookmarks/folders not sortable (the 'sortable' jquery function not work);
|
||||
- pluginBkmrksEdit: fired when a bookmarks/folder is removed, added or sorted, also when a folder is opened/closed;
|
||||
- pluginBkmrksOpenOpt: fired when the "Bookmarks Options" panel is opened (you can add new options);
|
||||
- pluginBkmrksSyncEnd: fired when the sync is finished;
|
||||
|
||||
***********************************************************************/
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// use own namespace for plugin
|
||||
window.plugin.bookmarks = function() {};
|
||||
@ -68,8 +47,16 @@
|
||||
|
||||
window.plugin.bookmarks.enableSync = false;
|
||||
|
||||
window.plugin.bookmarks.starLayers = {};
|
||||
window.plugin.bookmarks.starLayerGroup = null;
|
||||
|
||||
window.plugin.bookmarks.isSmart = undefined;
|
||||
window.plugin.bookmarks.isAndroid = function() { if(typeof android !== 'undefined' && android) { return true; } return false; }
|
||||
window.plugin.bookmarks.isAndroid = function() {
|
||||
if(typeof android !== 'undefined' && android) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*********************************************************************************************************************/
|
||||
|
||||
@ -262,11 +249,12 @@
|
||||
var guid = bkmrk['guid'];
|
||||
var btn_link = '<a class="bookmarksLink" onclick="$(\'a.bookmarksLink.selected\').removeClass(\'selected\');'+returnToMap+'window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false;">'+label+'</a>';
|
||||
}
|
||||
// Create the bookmark
|
||||
elementTemp += '<li class="bkmrk" id="'+idBkmrk+'">'+btn_remove+btn_link+'</li>';
|
||||
}
|
||||
elementTemp += '</li></ul>';
|
||||
|
||||
//Add folder 'Others' in last position
|
||||
// Add folder 'Others' in last position
|
||||
if(idFolders != window.plugin.bookmarks.KEY_OTHER_BKMRK) { element += elementTemp; }
|
||||
else{ elementExc = elementTemp; }
|
||||
}
|
||||
@ -286,9 +274,9 @@
|
||||
for(var idBkmrk in list[idFolders]['bkmrk']) {
|
||||
var portalGuid = list[idFolders]['bkmrk'][idBkmrk]['guid'];
|
||||
if(guid === portalGuid) {
|
||||
return {"folder":idFolders,"id":idBkmrk};
|
||||
return {"id_folder":idFolders,"id_bookmark":idBkmrk};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -321,7 +309,7 @@
|
||||
if(localStorage[window.plugin.bookmarks.KEY_STORAGE].search(guid) != -1) {
|
||||
var bkmrkData = window.plugin.bookmarks.findByGuid(guid);
|
||||
if(bkmrkData) {
|
||||
$('.bkmrk#'+bkmrkData['id']+' a.bookmarksLink').addClass('selected');
|
||||
$('.bkmrk#'+bkmrkData['id_bookmark']+' a.bookmarksLink').addClass('selected');
|
||||
$('.bkmrksStar').addClass('favorite');
|
||||
}
|
||||
}
|
||||
@ -335,12 +323,14 @@
|
||||
if($('.bkmrksStar').hasClass('favorite')) {
|
||||
var bkmrkData = window.plugin.bookmarks.findByGuid(guid);
|
||||
var list = window.plugin.bookmarks.bkmrksObj['portals'];
|
||||
delete list[bkmrkData['folder']]['bkmrk'][bkmrkData['id']];
|
||||
$('.bkmrk#'+bkmrkData['id']+'').remove();
|
||||
delete list[bkmrkData['id_folder']]['bkmrk'][bkmrkData['id_bookmark']];
|
||||
$('.bkmrk#'+bkmrkData['id_bookmark']+'').remove();
|
||||
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
window.plugin.bookmarks.updateStarPortal();
|
||||
window.runHooks('pluginBkmrksEdit');
|
||||
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "portal", "action": "remove", "folder": bkmrkData['id_folder'], "id": bkmrkData['id_bookmark'], "guid":guid});
|
||||
console.log('BOOKMARKS: removed portal ('+bkmrkData['id_bookmark']+' situated in '+bkmrkData['id_folder']+' folder)');
|
||||
}
|
||||
// If portal isn't saved in bookmarks: Add this bookmark
|
||||
else{
|
||||
@ -357,8 +347,9 @@
|
||||
window.plugin.bookmarks.bkmrksObj['portals'][window.plugin.bookmarks.KEY_OTHER_BKMRK]['bkmrk'][ID] = {"guid":guid,"latlng":latlng,"label":label};
|
||||
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
window.runHooks('pluginBkmrksEdit');
|
||||
window.plugin.bookmarks.refreshBkmrks();
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "portal", "action": "add", "id": ID});
|
||||
console.log('BOOKMARKS: added portal '+ID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,8 +382,9 @@
|
||||
window.plugin.bookmarks.bkmrksObj[short_type][ID] = {"label":label,"state":1,"bkmrk":{}};
|
||||
}
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
window.runHooks('pluginBkmrksEdit');
|
||||
window.plugin.bookmarks.refreshBkmrks();
|
||||
window.runHooks('pluginBkmrksEdit', {"target": type, "action": "add", "id": ID});
|
||||
console.log('BOOKMARKS: added '+type+' '+ID);
|
||||
}
|
||||
|
||||
// Remove BOOKMARK/FOLDER
|
||||
@ -401,12 +393,23 @@
|
||||
var typeList = $(elem).parent().parent().parent().parent().parent('div').attr('id');
|
||||
var ID = $(elem).parent('li').attr('id');
|
||||
var IDfold = $(elem).parent().parent().parent('li').attr('id');
|
||||
var guid = window.plugin.bookmarks.bkmrksObj[typeList.replace('bkmrk_', '')][IDfold]['bkmrk'][ID].guid;
|
||||
|
||||
delete window.plugin.bookmarks.bkmrksObj[typeList.replace('bkmrk_', '')][IDfold]['bkmrk'][ID];
|
||||
$(elem).parent('li').remove();
|
||||
|
||||
if(type === 'portals') {
|
||||
var list = window.plugin.bookmarks.bkmrksObj['portals'];
|
||||
|
||||
window.plugin.bookmarks.updateStarPortal();
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "portal", "action": "remove", "folder": IDfold, "id": ID, "guid": guid});
|
||||
console.log('BOOKMARKS: removed portal ('+ID+' situated in '+IDfold+' folder)');
|
||||
} else {
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "map", "action": "remove", "id": ID});
|
||||
console.log('BOOKMARKS: removed map '+ID);
|
||||
}
|
||||
}
|
||||
else if(type === 'folder') {
|
||||
@ -415,9 +418,11 @@
|
||||
|
||||
delete plugin.bookmarks.bkmrksObj[typeList.replace('bkmrk_', '')][ID];
|
||||
$(elem).parent().parent('li').remove();
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
window.plugin.bookmarks.updateStarPortal();
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "folder", "action": "remove", "id": ID});
|
||||
console.log('BOOKMARKS: removed folder '+ID);
|
||||
}
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
window.runHooks('pluginBkmrksEdit');
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************************************************/
|
||||
@ -433,7 +438,9 @@
|
||||
});
|
||||
window.plugin.bookmarks.bkmrksObj[keyType] = newArr;
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
window.runHooks('pluginBkmrksEdit');
|
||||
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "folder", "action": "sort"});
|
||||
console.log('BOOKMARKS: sorted folder');
|
||||
}
|
||||
|
||||
// Saved the new sort of the bookmarks (in the localStorage)
|
||||
@ -465,7 +472,8 @@
|
||||
});
|
||||
window.plugin.bookmarks.bkmrksObj[keyType] = newArr;
|
||||
window.plugin.bookmarks.saveStorage();
|
||||
window.runHooks('pluginBkmrksEdit');
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "bookmarks", "action": "sort"});
|
||||
console.log('BOOKMARKS: sorted bookmark (portal/map)');
|
||||
}
|
||||
|
||||
window.plugin.bookmarks.jquerySortableScript = function() {
|
||||
@ -534,8 +542,9 @@
|
||||
if(promptAction !== null && promptAction !== '') {
|
||||
localStorage[window.plugin.bookmarks.KEY_STORAGE] = promptAction;
|
||||
window.plugin.bookmarks.refreshBkmrks();
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "all", "action": "import"});
|
||||
console.log('BOOKMARKS: resetted and imported bookmarks');
|
||||
window.plugin.bookmarks.optAlert('Succesful. ');
|
||||
window.runHooks('pluginBkmrksEdit');
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,9 +554,9 @@
|
||||
delete localStorage[window.plugin.bookmarks.KEY_STORAGE];
|
||||
window.plugin.bookmarks.createStorage();
|
||||
window.plugin.bookmarks.loadStorage();
|
||||
|
||||
window.plugin.bookmarks.refreshBkmrks();
|
||||
window.runHooks('pluginBkmrksEdit');
|
||||
window.runHooks('pluginBkmrksEdit', {"target": "all", "action": "reset"});
|
||||
console.log('BOOKMARKS: resetted all bookmarks');
|
||||
window.plugin.bookmarks.optAlert('Succesful. ');
|
||||
}
|
||||
}
|
||||
@ -581,7 +590,7 @@
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************************************************/
|
||||
/** AUTO DRAWER ************************************************************************************************************************************************/
|
||||
/** AUTO DRAW **************************************************************************************************************************************************/
|
||||
/***************************************************************************************************************************************************************/
|
||||
window.plugin.bookmarks.dialogDrawer = function() {
|
||||
dialog({
|
||||
@ -590,17 +599,16 @@
|
||||
title:'Bookmarks - Auto Draw',
|
||||
buttons:{
|
||||
'DRAW': function() {
|
||||
window.plugin.bookmarks.draw();
|
||||
window.plugin.bookmarks.draw(0);
|
||||
},
|
||||
'REFRESH LIST': function() {
|
||||
$(this).dialog('close');
|
||||
window.plugin.bookmarks.dialogDrawer();
|
||||
'DRAW&VIEW': function() {
|
||||
window.plugin.bookmarks.draw(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.plugin.bookmarks.draw = function() {
|
||||
window.plugin.bookmarks.draw = function(view) {
|
||||
var latlngs = [];
|
||||
var uuu = $('#bkmrksAutoDrawer a.bkmrk.selected').each(function(i) {
|
||||
var tt = $(this).data('latlng');
|
||||
@ -609,7 +617,8 @@
|
||||
|
||||
if(latlngs.length >= 2 && latlngs.length <= 3) {
|
||||
var newItem;
|
||||
var options = {color:"#f06eaa",weight:4,opacity:.5}
|
||||
// var options = {color:"#a24ac3",weight:4,opacity:.5}
|
||||
var options = window.plugin.drawTools.polygonOptions;
|
||||
|
||||
if(latlngs.length == 3) { newItem = L.geodesicPolygon(latlngs, options); }
|
||||
else if(latlngs.length == 2) { newItem = L.geodesicPolyline(latlngs, options); }
|
||||
@ -622,7 +631,15 @@
|
||||
if(window.plugin.bookmarks.isSmart) {
|
||||
window.show('map');
|
||||
}
|
||||
map.fitBounds(newItem.getBounds());
|
||||
|
||||
// Shown the layer if it is hidden
|
||||
if(!map.hasLayer(window.plugin.drawTools.drawnItems)) {
|
||||
map.addLayer(window.plugin.drawTools.drawnItems);
|
||||
}
|
||||
|
||||
if(view) {
|
||||
map.fitBounds(newItem.getBounds());
|
||||
}
|
||||
}
|
||||
else{
|
||||
$('#bkmrksAutoDrawer p').toggle().delay('2500').fadeOut('500');
|
||||
@ -630,7 +647,7 @@
|
||||
}
|
||||
|
||||
window.plugin.bookmarks.dialogLoadList = function() {
|
||||
var r = '<span>The"<a href="http://iitc.jonatkins.com/?page=desktop#plugin-draw-tools" target="_BLANK"><strong>Draw Tools</strong></a>" plugin is required.</span>';
|
||||
var r = 'The "<a href="http://iitc.jonatkins.com/?page=desktop#plugin-draw-tools" target="_BLANK"><strong>Draw Tools</strong></a>" plugin is required.</span>';
|
||||
|
||||
if(!window.plugin.bookmarks || !window.plugin.drawTools) {
|
||||
$('.ui-dialog-autodrawer .ui-dialog-buttonset .ui-button:not(:first)').hide();
|
||||
@ -727,6 +744,8 @@
|
||||
delete window.plugin.bookmarks.updateQueue[e.property];
|
||||
window.plugin.bookmarks.storeLocal(window.plugin.bookmarks.UPDATE_QUEUE);
|
||||
window.plugin.bookmarks.refreshBkmrks();
|
||||
window.runHooks('pluginBkmrksSyncEnd', {"target": "all", "action": "sync"});
|
||||
console.log('BOOKMARKS: synchronized all');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -752,7 +771,9 @@
|
||||
window.plugin.bookmarks.loadLocal = function(mapping) {
|
||||
var objectJSON = localStorage[mapping.key];
|
||||
if(!objectJSON) return;
|
||||
window.plugin.bookmarks[mapping.field] = mapping.convertFunc ? mapping.convertFunc(JSON.parse(objectJSON)) : JSON.parse(objectJSON);
|
||||
window.plugin.bookmarks[mapping.field] = mapping.convertFunc
|
||||
? mapping.convertFunc(JSON.parse(objectJSON))
|
||||
: JSON.parse(objectJSON);
|
||||
}
|
||||
|
||||
window.plugin.bookmarks.syncBkmrks = function() {
|
||||
@ -764,6 +785,79 @@
|
||||
window.plugin.bookmarks.delaySync();
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************************************************/
|
||||
/** HIGHLIGHTER ************************************************************************************************************************************************/
|
||||
/***************************************************************************************************************************************************************/
|
||||
window.plugin.bookmarks.highlight = function(data) {
|
||||
var guid = data.portal.options.ent[0];
|
||||
if(window.plugin.bookmarks.findByGuid(guid)) {
|
||||
data.portal.setStyle({fillColor:'red'});
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.bookmarks.highlightRefresh = function(data) {
|
||||
if(_current_highlighter === 'Bookmarked Portals') {
|
||||
if(data.action === 'sync' || data.target === 'portal' || (data.target === 'folder' && data.action === 'remove') || (data.target === 'all' && data.action === 'import') || (data.target === 'all' && data.action === 'reset')) {
|
||||
window.resetHighlightedPortals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************************************************/
|
||||
/** BOOKMARKED PORTALS LAYER ***********************************************************************************************************************************/
|
||||
/***************************************************************************************************************************************************************/
|
||||
window.plugin.bookmarks.addAllStars = function() {
|
||||
var list = window.plugin.bookmarks.bkmrksObj.portals;
|
||||
|
||||
for(var idFolders in list) {
|
||||
for(var idBkmrks in list[idFolders]['bkmrk']) {
|
||||
var latlng = list[idFolders]['bkmrk'][idBkmrks].latlng.split(",");
|
||||
var guid = list[idFolders]['bkmrk'][idBkmrks].guid;
|
||||
window.plugin.bookmarks.addStar(guid, latlng);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.bookmarks.resetAllStars = function() {
|
||||
for(guid in window.plugin.bookmarks.starLayers) {
|
||||
var starInLayer = window.plugin.bookmarks.starLayers[guid];
|
||||
window.plugin.bookmarks.starLayerGroup.removeLayer(starInLayer);
|
||||
delete window.plugin.bookmarks.starLayers[guid];
|
||||
}
|
||||
window.plugin.bookmarks.addAllStars();
|
||||
}
|
||||
|
||||
window.plugin.bookmarks.addStar = function(guid, latlng) {
|
||||
var star = L.marker(latlng, {
|
||||
icon: L.icon({
|
||||
iconUrl: '@@INCLUDEIMAGE:images/marker-star.png@@',
|
||||
iconAnchor: [15,40],
|
||||
iconSize: [30,40]
|
||||
})
|
||||
});
|
||||
window.plugin.bookmarks.starLayers[guid] = star;
|
||||
star.addTo(window.plugin.bookmarks.starLayerGroup);
|
||||
}
|
||||
|
||||
window.plugin.bookmarks.editStar = function(data) {
|
||||
if(data.target === 'portal') {
|
||||
if(data.action === 'add') {
|
||||
var guid = window.selectedPortal;
|
||||
var latlng = window.portals[guid]._latlng;
|
||||
var starInLayer = window.plugin.bookmarks.starLayers[data.guid];
|
||||
window.plugin.bookmarks.addStar(guid, latlng);
|
||||
}
|
||||
else if(data.action === 'remove') {
|
||||
var starInLayer = window.plugin.bookmarks.starLayers[data.guid];
|
||||
window.plugin.bookmarks.starLayerGroup.removeLayer(starInLayer);
|
||||
delete window.plugin.bookmarks.starLayers[data.guid];
|
||||
}
|
||||
}
|
||||
else if((data.target === 'all' && (data.action === 'import' || data.action === 'reset')) || (data.target === 'folder' && data.action === 'remove')) {
|
||||
window.plugin.bookmarks.resetAllStars();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************************************************/
|
||||
|
||||
window.plugin.bookmarks.setupCSS = function() {
|
||||
@ -776,54 +870,55 @@
|
||||
|
||||
plugin.bookmarks.htmlBoxTrigger = '<a id="bkmrksTrigger" class="open" onclick="window.plugin.bookmarks.switchStatusBkmrksBox('+ttt+');return false;">[-] Bookmarks</a>';
|
||||
plugin.bookmarks.htmlBkmrksBox = '<div id="bookmarksBox">'
|
||||
+'<div id="topBar">'
|
||||
+'<a id="bookmarksMin" class="btn" onclick="window.plugin.bookmarks.switchStatusBkmrksBox(0);return false;" title="Minimize">-</a>'
|
||||
+'<div class="handle">...</div>'
|
||||
+'</div>'
|
||||
+'<div id="bookmarksTypeBar">'
|
||||
+'<h5 class="bkmrk_maps current" onclick="window.plugin.bookmarks.switchPageBkmrksBox(this, 0);return false">Maps</h5>'
|
||||
+'<h5 class="bkmrk_portals" onclick="window.plugin.bookmarks.switchPageBkmrksBox(this, 1);return false">Portals</h5>'
|
||||
+'<div style="clear:both !important;"></div>'
|
||||
+'</div>'
|
||||
+'<div id="bkmrk_maps" class="bookmarkList current">'
|
||||
+'<div class="addForm">'
|
||||
+'<input placeholder="Insert label" />'
|
||||
+'<a class="newMap" onclick="window.plugin.bookmarks.addElement(this, \'map\');return false;">+ Map</a>'
|
||||
+'<a class="newFolder" onclick="window.plugin.bookmarks.addElement(this, \'folder\');return false;">+ Folder</a>'
|
||||
+'</div>'
|
||||
+'</div>'
|
||||
+'<div id="bkmrk_portals" class="bookmarkList">'
|
||||
+'<div class="addForm">'
|
||||
+'<input placeholder="Insert label" />'
|
||||
+'<a class="newFolder" onclick="window.plugin.bookmarks.addElement(this, \'folder\');return false;">+ Folder</a>'
|
||||
+'</div>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
+'<div id="topBar">'
|
||||
+'<a id="bookmarksMin" class="btn" onclick="window.plugin.bookmarks.switchStatusBkmrksBox(0);return false;" title="Minimize">-</a>'
|
||||
+'<div class="handle">...</div>'
|
||||
+'</div>'
|
||||
+'<div id="bookmarksTypeBar">'
|
||||
+'<h5 class="bkmrk_maps current" onclick="window.plugin.bookmarks.switchPageBkmrksBox(this, 0);return false">Maps</h5>'
|
||||
+'<h5 class="bkmrk_portals" onclick="window.plugin.bookmarks.switchPageBkmrksBox(this, 1);return false">Portals</h5>'
|
||||
+'<div style="clear:both !important;"></div>'
|
||||
+'</div>'
|
||||
+'<div id="bkmrk_maps" class="bookmarkList current">'
|
||||
+'<div class="addForm">'
|
||||
+'<input placeholder="Insert label" />'
|
||||
+'<a class="newMap" onclick="window.plugin.bookmarks.addElement(this, \'map\');return false;">+ Map</a>'
|
||||
+'<a class="newFolder" onclick="window.plugin.bookmarks.addElement(this, \'folder\');return false;">+ Folder</a>'
|
||||
+'</div>'
|
||||
+'</div>'
|
||||
+'<div id="bkmrk_portals" class="bookmarkList">'
|
||||
+'<div class="addForm">'
|
||||
+'<input placeholder="Insert label" />'
|
||||
+'<a class="newFolder" onclick="window.plugin.bookmarks.addElement(this, \'folder\');return false;">+ Folder</a>'
|
||||
+'</div>'
|
||||
+'</div>'
|
||||
+'</div>';
|
||||
|
||||
plugin.bookmarks.htmlDisabledMessage = '<div title="Your browser do not support localStorage">Plugin Bookmarks disabled*.</div>';
|
||||
plugin.bookmarks.htmlStar = '<a class="bkmrksStar" onclick="window.plugin.bookmarks.switchStarPortal();return false;" title="Save this portal in your bookmarks"><span></span></a>';
|
||||
plugin.bookmarks.htmlCalldrawBox = '<a onclick="window.plugin.bookmarks.dialogDrawer();return false;" title="Draw lines/triangles between bookmarked portals">Auto draw</a>';
|
||||
plugin.bookmarks.htmlCallSetBox = '<a onclick="window.plugin.bookmarks.manualOpt();return false;">Bookmarks Opt</a>';
|
||||
plugin.bookmarks.htmlSetbox = '<div id="bkmrksSetbox">'
|
||||
+'<a onclick="window.plugin.bookmarks.optCopy();">Copy</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optPaste();return false;">Paste/Import</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optReset();return false;">Reset</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optShare();">Share all Bookmarks (only mobile)</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optBox(\'save\');">Save box position (only desktop)</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optBox(\'reset\');">Reset box position (only desktop)</a>'
|
||||
+'</div>';
|
||||
+'<a onclick="window.plugin.bookmarks.optCopy();">Copy/Export Bookmarks</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optPaste();return false;">Paste/Import Bookmarks</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optReset();return false;">Reset Bookmarks</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optShare();">Share all Bookmarks (IITCm)</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optBox(\'save\');">Save box position (No IITCm)</a>'
|
||||
+'<a onclick="window.plugin.bookmarks.optBox(\'reset\');">Reset box position (No IITCm)</a>'
|
||||
+'</div>';
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************************************************/
|
||||
|
||||
var setup = function() {
|
||||
|
||||
window.plugin.bookmarks.isSmart = window.isSmartphone();
|
||||
|
||||
// Fired when a bookmarks/folder is removed, added or sorted, also when a folder is opened/closed.
|
||||
if($.inArray('pluginBkmrksEdit', window.VALID_HOOKS) < 0) { window.VALID_HOOKS.push('pluginBkmrksEdit'); }
|
||||
// Fired when the "Bookmarks Options" panell is opened (you can add new options);
|
||||
if($.inArray('pluginBkmrksOpenOpt', window.VALID_HOOKS) < 0) { window.VALID_HOOKS.push('pluginBkmrksOpenOpt'); }
|
||||
// Fired when the sync is finished;
|
||||
if($.inArray('pluginBkmrksSyncEnd', window.VALID_HOOKS) < 0) { window.VALID_HOOKS.push('pluginBkmrksSyncEnd'); }
|
||||
|
||||
// If the storage not exists or is a old version
|
||||
window.plugin.bookmarks.createStorage();
|
||||
@ -849,23 +944,6 @@
|
||||
$('.bkmrksStar').remove();
|
||||
}
|
||||
});
|
||||
|
||||
// in the future i hope in a 'portalClosed' hook
|
||||
/* hook done
|
||||
window.unselectOldPortal = function() {
|
||||
var oldPortal = portals[selectedPortal];
|
||||
if(oldPortal) portalResetColor(oldPortal);
|
||||
selectedPortal = null;
|
||||
$('#portaldetails').html('');
|
||||
if(isSmartphone()) {
|
||||
$('.fullimg').remove();
|
||||
$('#mobileinfo').html('');
|
||||
}
|
||||
clearPortalIndicators();
|
||||
$('.bkmrksStar').remove();
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
$('#toolbox').append(window.plugin.bookmarks.htmlCallSetBox+window.plugin.bookmarks.htmlCalldrawBox);
|
||||
|
||||
@ -877,10 +955,24 @@
|
||||
if(window.plugin.bookmarks.statusBox['page'] === 1) { $('#bookmarksBox h5.bkmrk_portals').trigger('click'); }
|
||||
|
||||
window.addHook('portalDetailsUpdated', window.plugin.bookmarks.addStarToSidebar);
|
||||
|
||||
// Sync
|
||||
window.addHook('pluginBkmrksEdit', window.plugin.bookmarks.syncBkmrks);
|
||||
window.addHook('iitcLoaded', window.plugin.bookmarks.registerFieldForSyncing);
|
||||
|
||||
// Highlighter - bookmarked portals
|
||||
window.addHook('pluginBkmrksEdit', window.plugin.bookmarks.highlightRefresh);
|
||||
window.addHook('pluginBkmrksSyncEnd', window.plugin.bookmarks.highlightRefresh);
|
||||
window.addPortalHighlighter('Bookmarked Portals', window.plugin.bookmarks.highlight);
|
||||
|
||||
// Layer - Bookmarked portals
|
||||
window.plugin.bookmarks.starLayerGroup = new L.LayerGroup();
|
||||
window.addLayerGroup('Bookmarked Portals', window.plugin.bookmarks.starLayerGroup, false);
|
||||
window.plugin.bookmarks.addAllStars();
|
||||
window.addHook('pluginBkmrksEdit', window.plugin.bookmarks.editStar);
|
||||
window.addHook('pluginBkmrksSyncEnd', window.plugin.bookmarks.resetAllStars);
|
||||
}
|
||||
|
||||
// PLUGIN END //////////////////////////////////////////////////////////
|
||||
|
||||
@@PLUGINEND@@
|
||||
@@PLUGINEND@@
|
@ -223,7 +223,7 @@
|
||||
display:none;
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:250px;
|
||||
left:277px;
|
||||
width:47px;
|
||||
margin-top:-36px;
|
||||
height:64px;
|
||||
@ -243,7 +243,8 @@
|
||||
width:auto;
|
||||
}
|
||||
#bkmrksTrigger, .bkmrksStar span{
|
||||
background-image:url(@@INCLUDEIMAGE:plugins/bookmarks-img.png@@);}
|
||||
background-image:url(@@INCLUDEIMAGE:plugins/bookmarks-img.png@@);
|
||||
}
|
||||
.bkmrksStar span{
|
||||
display:inline-block;
|
||||
float:left;
|
||||
|
@ -2,7 +2,7 @@
|
||||
// @id iitc-plugin-draw-tools@breunigs
|
||||
// @name IITC plugin: draw tools
|
||||
// @category Layer
|
||||
// @version 0.5.1.@@DATETIMEVERSION@@
|
||||
// @version 0.5.3.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
@ -197,7 +197,7 @@ window.plugin.drawTools.load = function() {
|
||||
layer = L.geodesicPolygon(item.latLngs,window.plugin.drawTools.polygonOptions);
|
||||
break;
|
||||
case 'circle':
|
||||
layer = L.circle(item.latLng,item.radius,window.plugin.drawTools.polygonOptions);
|
||||
layer = L.geodesicCircle(item.latLng,item.radius,window.plugin.drawTools.polygonOptions);
|
||||
break;
|
||||
case 'marker':
|
||||
layer = L.marker(item.latLng,window.plugin.drawTools.markerOptions)
|
||||
|
@ -19,7 +19,7 @@
|
||||
// PLUGIN START ////////////////////////////////////////////////////////
|
||||
window.PLAYER_TRACKER_MAX_TIME = 3*60*60*1000; // in milliseconds
|
||||
window.PLAYER_TRACKER_MIN_ZOOM = 9;
|
||||
|
||||
window.PLAYER_TRACKER_MIN_OPACITY = 0.3;
|
||||
window.PLAYER_TRACKER_LINE_COLOUR = '#FF00FD';
|
||||
|
||||
|
||||
@ -45,11 +45,18 @@ window.plugin.playerTracker.setup = function() {
|
||||
iconRetinaUrl: iconResRetImage
|
||||
}});
|
||||
|
||||
plugin.playerTracker.drawnTraces = new L.LayerGroup();
|
||||
window.addLayerGroup('Player Tracker', plugin.playerTracker.drawnTraces, true);
|
||||
plugin.playerTracker.drawnTracesEnl = new L.LayerGroup();
|
||||
plugin.playerTracker.drawnTracesRes = new L.LayerGroup();
|
||||
// to avoid any favouritism, we'll put the player's own faction layer first
|
||||
if (PLAYER.team == 'RESISTANCE') {
|
||||
window.addLayerGroup('Player Tracker Resistance', plugin.playerTracker.drawnTracesRes, true);
|
||||
window.addLayerGroup('Player Tracker Enlightened', plugin.playerTracker.drawnTracesEnl, true);
|
||||
} else {
|
||||
window.addLayerGroup('Player Tracker Enlightened', plugin.playerTracker.drawnTracesEnl, true);
|
||||
window.addLayerGroup('Player Tracker Resistance', plugin.playerTracker.drawnTracesRes, true);
|
||||
}
|
||||
map.on('layeradd',function(obj) {
|
||||
if(obj.layer === plugin.playerTracker.drawnTraces)
|
||||
{
|
||||
if(obj.layer === plugin.playerTracker.drawnTracesEnl || obj.layer === plugin.playerTracker.drawnTracesRes) {
|
||||
obj.layer.eachLayer(function(marker) {
|
||||
if(marker._icon) window.setupTooltips($(marker._icon));
|
||||
});
|
||||
@ -77,7 +84,8 @@ window.plugin.playerTracker.stored = {};
|
||||
window.plugin.playerTracker.zoomListener = function() {
|
||||
var ctrl = $('.leaflet-control-layers-selector + span:contains("Player Tracker")').parent();
|
||||
if(window.map.getZoom() < window.PLAYER_TRACKER_MIN_ZOOM) {
|
||||
window.plugin.playerTracker.drawnTraces.clearLayers();
|
||||
window.plugin.playerTracker.drawnTracesEnl.clearLayers();
|
||||
window.plugin.playerTracker.drawnTracesRes.clearLayers();
|
||||
ctrl.addClass('disabled').attr('title', 'Zoom in to show those.');
|
||||
} else {
|
||||
ctrl.removeClass('disabled').attr('title', '');
|
||||
@ -241,9 +249,10 @@ window.plugin.playerTracker.ago = function(time, now) {
|
||||
|
||||
window.plugin.playerTracker.drawData = function() {
|
||||
var gllfe = plugin.playerTracker.getLatLngFromEvent;
|
||||
var layer = plugin.playerTracker.drawnTraces;
|
||||
|
||||
var polyLineByAge = [[], [], [], []];
|
||||
var polyLineByAgeEnl = [[], [], [], []];
|
||||
var polyLineByAgeRes = [[], [], [], []];
|
||||
|
||||
var split = PLAYER_TRACKER_MAX_TIME / 4;
|
||||
var now = new Date().getTime();
|
||||
$.each(plugin.playerTracker.stored, function(pguid, playerData) {
|
||||
@ -259,7 +268,11 @@ window.plugin.playerTracker.drawData = function() {
|
||||
var p = playerData.events[i];
|
||||
var ageBucket = Math.min(parseInt((now - p.time) / split), 4-1);
|
||||
var line = [gllfe(p), gllfe(playerData.events[i-1])];
|
||||
polyLineByAge[ageBucket].push(line);
|
||||
|
||||
if(playerData.team === 'RESISTANCE')
|
||||
polyLineByAgeRes[ageBucket].push(line);
|
||||
else
|
||||
polyLineByAgeEnl[ageBucket].push(line);
|
||||
}
|
||||
|
||||
// tooltip for marker
|
||||
@ -310,19 +323,23 @@ window.plugin.playerTracker.drawData = function() {
|
||||
}
|
||||
});
|
||||
|
||||
// marker opacity
|
||||
var relOpacity = 1 - (now - last.time) / window.PLAYER_TRACKER_MAX_TIME
|
||||
var absOpacity = window.PLAYER_TRACKER_MIN_OPACITY + (1 - window.PLAYER_TRACKER_MIN_OPACITY) * relOpacity;
|
||||
|
||||
// marker itself
|
||||
var icon = playerData.team === 'RESISTANCE' ? new plugin.playerTracker.iconRes() : new plugin.playerTracker.iconEnl();
|
||||
var m = L.marker(gllfe(last), {title: title, icon: icon, referenceToPortal: closestPortal});
|
||||
var m = L.marker(gllfe(last), {title: title, icon: icon, referenceToPortal: closestPortal, opacity: absOpacity});
|
||||
// ensure tooltips are closed, sometimes they linger
|
||||
m.on('mouseout', function() { $(this._icon).tooltip('close'); });
|
||||
m.addTo(layer);
|
||||
m.addTo(playerData.team === 'RESISTANCE' ? plugin.playerTracker.drawnTracesRes : plugin.playerTracker.drawnTracesEnl);
|
||||
plugin.playerTracker.oms.addMarker(m);
|
||||
// jQueryUI doesn’t automatically notice the new markers
|
||||
window.setupTooltips($(m._icon));
|
||||
});
|
||||
|
||||
// draw the poly lines to the map
|
||||
$.each(polyLineByAge, function(i, polyLine) {
|
||||
$.each(polyLineByAgeEnl, function(i, polyLine) {
|
||||
if(polyLine.length === 0) return true;
|
||||
|
||||
var opts = {
|
||||
@ -333,7 +350,20 @@ window.plugin.playerTracker.drawData = function() {
|
||||
dashArray: "5,8"
|
||||
};
|
||||
|
||||
L.multiPolyline(polyLine, opts).addTo(layer);
|
||||
L.multiPolyline(polyLine, opts).addTo(plugin.playerTracker.drawnTracesEnl);
|
||||
});
|
||||
$.each(polyLineByAgeRes, function(i, polyLine) {
|
||||
if(polyLine.length === 0) return true;
|
||||
|
||||
var opts = {
|
||||
weight: 2-0.25*i,
|
||||
color: PLAYER_TRACKER_LINE_COLOUR,
|
||||
clickable: false,
|
||||
opacity: 1-0.2*i,
|
||||
dashArray: "5,8"
|
||||
};
|
||||
|
||||
L.multiPolyline(polyLine, opts).addTo(plugin.playerTracker.drawnTracesRes);
|
||||
});
|
||||
}
|
||||
|
||||
@ -343,11 +373,15 @@ window.plugin.playerTracker.handleData = function(data) {
|
||||
plugin.playerTracker.discardOldData();
|
||||
plugin.playerTracker.processNewData(data);
|
||||
// remove old popups
|
||||
plugin.playerTracker.drawnTraces.eachLayer(function(layer) {
|
||||
plugin.playerTracker.drawnTracesEnl.eachLayer(function(layer) {
|
||||
if(layer._icon) $(layer._icon).tooltip('destroy');
|
||||
});
|
||||
plugin.playerTracker.drawnTracesRes.eachLayer(function(layer) {
|
||||
if(layer._icon) $(layer._icon).tooltip('destroy');
|
||||
});
|
||||
plugin.playerTracker.oms.clearMarkers();
|
||||
plugin.playerTracker.drawnTraces.clearLayers();
|
||||
plugin.playerTracker.drawnTracesEnl.clearLayers();
|
||||
plugin.playerTracker.drawnTracesRes.clearLayers();
|
||||
plugin.playerTracker.drawData();
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// @id iitc-plugin-portal-names@zaso
|
||||
// @name IITC plugin: Portal Names
|
||||
// @category Layer
|
||||
// @version 0.1.0.@@DATETIMEVERSION@@
|
||||
// @version 0.1.2.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
@ -21,7 +21,6 @@
|
||||
// use own namespace for plugin
|
||||
window.plugin.portalNames = function() {};
|
||||
|
||||
window.plugin.portalNames.MAX_PORTALS = 250;
|
||||
window.plugin.portalNames.NAME_WIDTH = 80;
|
||||
window.plugin.portalNames.NAME_HEIGHT = 23;
|
||||
|
||||
@ -88,38 +87,49 @@ window.plugin.portalNames.updatePortalLabels = function() {
|
||||
for (var guid in window.portals) {
|
||||
var p = window.portals[guid];
|
||||
if (p._map) { // only consider portals added to the map
|
||||
var point = map.latLngToLayerPoint(p.getLatLng());
|
||||
var point = map.project(p.getLatLng());
|
||||
portalPoints[guid] = point;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(portalPoints).length > window.plugin.portalNames.MAX_PORTALS) {
|
||||
// too manuy VISIBLE portals to handle quickly - clear all
|
||||
window.plugin.portalNames.labelLayerGroup.clearLayers();
|
||||
window.plugin.portalNames.labelLayers = {};
|
||||
return;
|
||||
}
|
||||
// for efficient testing of intersection, group portals into buckets based on the label size
|
||||
var buckets = {};
|
||||
for (var guid in portalPoints) {
|
||||
var point = portalPoints[guid];
|
||||
|
||||
var bucketId = L.point([Math.floor(point.x/(window.plugin.portalNames.NAME_WIDTH*2)),Math.floor(point.y/window.plugin.portalNames.NAME_HEIGHT)]);
|
||||
// the guid is added to four buckets. this way, when testing for overlap we don't need to test
|
||||
// all 8 buckets surrounding the one around the particular portal, only the bucket it is in itself
|
||||
var bucketIds = [bucketId, bucketId.add([1,0]), bucketId.add([0,1]), bucketId.add([1,1])];
|
||||
for (var i in bucketIds) {
|
||||
var b = bucketIds[i].toString();
|
||||
if (!buckets[b]) buckets[b] = {};
|
||||
buckets[b][guid] = true;
|
||||
}
|
||||
}
|
||||
|
||||
var coveredPortals = {};
|
||||
|
||||
for (var guid in portalPoints) {
|
||||
var point = portalPoints[guid];
|
||||
// the bounds used for testing are twice as wide as the portal name marker. this is so that there's no left/right
|
||||
// overlap between two different portals text
|
||||
var largeBounds = L.bounds (
|
||||
point.subtract([window.plugin.portalNames.NAME_WIDTH,0]),
|
||||
point.add([window.plugin.portalNames.NAME_WIDTH,window.plugin.portalNames.NAME_HEIGHT])
|
||||
);
|
||||
|
||||
for (var otherGuid in portalPoints) {
|
||||
if (guid != otherGuid) {
|
||||
var otherPoint = portalPoints[otherGuid];
|
||||
|
||||
if (largeBounds.contains(otherPoint)) {
|
||||
// another portal is within the rectangle for this one's name - so no name for this one
|
||||
coveredPortals[guid] = true;
|
||||
break;
|
||||
for (var bucket in buckets) {
|
||||
var bucketGuids = buckets[bucket];
|
||||
for (var guid in bucketGuids) {
|
||||
var point = portalPoints[guid];
|
||||
// the bounds used for testing are twice as wide as the portal name marker. this is so that there's no left/right
|
||||
// overlap between two different portals text
|
||||
var largeBounds = L.bounds (
|
||||
point.subtract([window.plugin.portalNames.NAME_WIDTH,0]),
|
||||
point.add([window.plugin.portalNames.NAME_WIDTH,window.plugin.portalNames.NAME_HEIGHT])
|
||||
);
|
||||
|
||||
for (var otherGuid in bucketGuids) {
|
||||
if (guid != otherGuid) {
|
||||
var otherPoint = portalPoints[otherGuid];
|
||||
|
||||
if (largeBounds.contains(otherPoint)) {
|
||||
// another portal is within the rectangle for this one's name - so no name for this one
|
||||
coveredPortals[guid] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,6 +160,7 @@ var setup = function() {
|
||||
window.plugin.portalNames.labelLayerGroup = new L.LayerGroup();
|
||||
window.addLayerGroup('Portal Names', window.plugin.portalNames.labelLayerGroup, true);
|
||||
|
||||
window.addHook('requestFinished', window.plugin.portalNames.updatePortalLabels);
|
||||
window.addHook('mapDataRefreshEnd', window.plugin.portalNames.updatePortalLabels);
|
||||
window.map.on('overlayadd overlayremove', window.plugin.portalNames.updatePortalLabels);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// @id iitc-plugin-portals-list@teo96
|
||||
// @name IITC plugin: show list of portals
|
||||
// @category Info
|
||||
// @version 0.0.16.@@DATETIMEVERSION@@
|
||||
// @version 0.0.17.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
@ -146,7 +146,7 @@ window.plugin.portalslist.getPortals = function() {
|
||||
}
|
||||
}else { mods[ind] = ['', '', '']; }
|
||||
});
|
||||
console.log(mods);
|
||||
|
||||
var APgain= getAttackApGain(d).enemyAp;
|
||||
var thisPortal = {'portal': d,
|
||||
'name': name,
|
||||
@ -395,7 +395,7 @@ window.plugin.portalslist.getPortalLink = function(portal,guid) {
|
||||
onClick: jsSingleClick,
|
||||
onDblClick: jsDoubleClick
|
||||
})[0].outerHTML;
|
||||
var div = '<div style="max-height: 15px !important; min-width:140px !important;max-width:180px !important; overflow: hidden; text-overflow:ellipsis;">'+a+'</div>';
|
||||
var div = '<div class="portalTitle">'+a+'</div>';
|
||||
return div;
|
||||
}
|
||||
|
||||
@ -416,13 +416,14 @@ var setup = function() {
|
||||
$('#toolbox').append(' <a onclick="window.plugin.portalslist.displayPL()" title="Display a list of portals in the current view">Portals list</a>');
|
||||
$('head').append('<style>' +
|
||||
//style.css sets dialog max-width to 700px - override that here
|
||||
// (the width: 800 parameter to dialog is NOT enough to override that css limit)
|
||||
'#dialog-portal-list {max-width: 800px !important;}' +
|
||||
'#portalslist table {margin-top:5px; border-collapse: collapse; empty-cells: show; width:100%; clear: both;}' +
|
||||
'#portalslist table td, #portalslist table th {border-bottom: 1px solid #0b314e; padding:3px; color:white; background-color:#1b415e}' +
|
||||
'#portalslist table tr.res td { background-color: #005684; }' +
|
||||
'#portalslist table tr.enl td { background-color: #017f01; }' +
|
||||
'#portalslist table tr.neutral td { background-color: #000000; }' +
|
||||
'#portalslist table th { text-align:center;}' +
|
||||
'#portalslist table tr.res td { background-color: #005684; }' +
|
||||
'#portalslist table tr.enl td { background-color: #017f01; }' +
|
||||
'#portalslist table tr.neutral td { background-color: #000000; }' +
|
||||
'#portalslist table th { text-align: center;}' +
|
||||
'#portalslist table td { text-align: center;}' +
|
||||
'#portalslist table td.L0 { cursor: help; background-color: #000000 !important;}' +
|
||||
'#portalslist table td.L1 { cursor: help; background-color: #FECE5A !important;}' +
|
||||
@ -437,10 +438,11 @@ var setup = function() {
|
||||
'#portalslist table th { cursor:pointer; text-align: right;}' +
|
||||
'#portalslist table th:nth-child(1) { text-align: left;}' +
|
||||
'#portalslist table th.sorted { color:#FFCE00; }' +
|
||||
'#portalslist .filterAll { margin-top:10px;}' +
|
||||
'#portalslist .filterRes { margin-top:10px; background-color: #005684 }' +
|
||||
'#portalslist .filterEnl { margin-top:10px; background-color: #017f01 }' +
|
||||
'#portalslist .disclaimer { margin-top:10px; font-size:10px; }' +
|
||||
'#portalslist .filterAll { margin-top: 10px;}' +
|
||||
'#portalslist .filterRes { margin-top: 10px; background-color: #005684 }' +
|
||||
'#portalslist .filterEnl { margin-top: 10px; background-color: #017f01 }' +
|
||||
'#portalslist .disclaimer { margin-top: 10px; font-size:10px; }' +
|
||||
'#portalslist .portalTitle { display: inline-block; width: 160px !important; min-width: 160px !important; max-width: 160px !important; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }' +
|
||||
'</style>');
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ var setup = function() {
|
||||
$('head').append('<style>' +
|
||||
'.res #address { border: 1px solid #0076b6; }' +
|
||||
'.enl #address { border: 1px solid #017f01; }' +
|
||||
'#address { margin:5px; padding:3px; margin-top:110px; margin-right:8px; font-size:11px; background-color:rgba(0, 0, 0, 0.7); text-align:center; white-space:nowrap; overflow:hidden; }' +
|
||||
'#address { position: absolute; bottom: 0; left: 5px; right: 8px; padding: 3px; font-size: 11px; background-color: rgba(0, 0, 0, 0.7); text-align: center; overflow: hidden; }' +
|
||||
'</style>');
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,11 @@
|
||||
// @id iitc-plugin-show-less-portals@jonatkins
|
||||
// @name IITC plugin: Show less portals when zoomed out
|
||||
// @category Tweaks
|
||||
// @version 0.1.3.@@DATETIMEVERSION@@
|
||||
// @version 0.1.4.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Decrease the portal detail level used when zoomed out. This can speed up map loading, decrease the amount of data used, and result in faster display. Only applies when zoomed out to show no closer than L3 portals. May stop display of the smaller links/fields.
|
||||
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Decrease the portal detail level used when zoomed out. This can speed up map loading, decrease the amount of data used, and solve excessive request issues. Only applies when zoomed out to show no closer than L3 portals. May stop display of the smaller links/fields.
|
||||
// @include https://www.ingress.com/intel*
|
||||
// @include http://www.ingress.com/intel*
|
||||
// @match https://www.ingress.com/intel*
|
||||
@ -32,23 +32,21 @@ window.plugin.showLessPortals.setup = function() {
|
||||
window.getPortalDataZoom = function() {
|
||||
var mapZoom = map.getZoom();
|
||||
|
||||
// this plugin only cares about close in zoom levels (zoom 13 and higher) - run the original
|
||||
// code when this isn't the case. (this way, multiple zoom-modifying plugins can exist at once - in theory)
|
||||
if (mapZoom >= 13) {
|
||||
return origGetPortalDataZoom();
|
||||
// the latest intel site update, as of 2013-10-16, requests a silly number of map tiles at the larger zoom levels
|
||||
// IITC matches the behaviour by default, but it makes sense to reduce the detail level sooner
|
||||
|
||||
// at the largest scale zooms - move back two levels
|
||||
if (mapZoom <= 7) {
|
||||
return Math.max(mapZoom-2,0);
|
||||
}
|
||||
|
||||
// make sure we're dealing with an integer here
|
||||
// (mobile: a float somehow gets through in some cases!)
|
||||
var z = parseInt(mapZoom);
|
||||
// intermediate zoom levels - move back one
|
||||
if (mapZoom <= 11) {
|
||||
return Math.max(mapZoom-1,0);
|
||||
}
|
||||
|
||||
// reduce the portal zoom level by one
|
||||
z -= 1;
|
||||
|
||||
// ensure we're not too far out
|
||||
if (z < 0) z=0;
|
||||
|
||||
return z;
|
||||
// otherwise revert to default behaviour
|
||||
return origGetPortalDataZoom();
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,7 +130,7 @@ var setup = function () {
|
||||
'.showLinkedPortalLink2,.showLinkedPortalLink6,.showLinkedPortalLink10,.showLinkedPortalLink14 {top: 69px; }' +
|
||||
'.showLinkedPortalLink3,.showLinkedPortalLink7,.showLinkedPortalLink11,.showLinkedPortalLink15 {top: 113px; }' +
|
||||
'.showLinkedPortalLink4,.showLinkedPortalLink8,.showLinkedPortalLink12,.showLinkedPortalLink16 {top: 157px; }' +
|
||||
'#level{text-align:center; margin-right: 0px;}' +
|
||||
'#level{text-align: center; margin-right: -0.5em; position: relative; right: 50%; width: 1em;}' +
|
||||
'</style>');
|
||||
window.plugin.showLinkedPortal.setupCallback();
|
||||
}
|
||||
|
@ -2,11 +2,11 @@
|
||||
// @id iitc-plugin-show-more-portals@jonatkins
|
||||
// @name IITC plugin: Show more portals
|
||||
// @category Tweaks
|
||||
// @version 0.1.3.@@DATETIMEVERSION@@
|
||||
// @version 0.1.5.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Boost the detail level of portals shown on the map by one zoom level when zoomed in close (L2+ portals or closer)
|
||||
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Boost the detail level of portals shown so that unclaimed portals are visible when normally L1+ portals would be shown, and L2+ are visible when normally L3+ are shown
|
||||
// @include https://www.ingress.com/intel*
|
||||
// @include http://www.ingress.com/intel*
|
||||
// @match https://www.ingress.com/intel*
|
||||
@ -32,36 +32,22 @@ window.plugin.showMorePortals.setup = function() {
|
||||
window.getPortalDataZoom = function() {
|
||||
var mapZoom = map.getZoom();
|
||||
|
||||
// this plugin only cares about close in zoom levels (zoom 13 and higher) - run the original
|
||||
// code when this isn't the case. (this way, multiple zoom-modifying plugins can exist at once - in theory)
|
||||
if (mapZoom < 13) {
|
||||
return origGetPortalDataZoom();
|
||||
// as of 2013-10-16...
|
||||
|
||||
// the stock site uses the same tile size for both L1+ portals and all portals
|
||||
// therefore, changing the L1+ zoom levels into all portals zoom level is not unfriendly to the servers
|
||||
// (in some ways it's nicer, as IITC caches better)
|
||||
if (mapZoom >= 15) {
|
||||
return 17;
|
||||
}
|
||||
|
||||
// make sure we're dealing with an integer here
|
||||
// (mobile: a float somehow gets through in some cases!)
|
||||
var z = parseInt(mapZoom);
|
||||
|
||||
// boost data zoom level by one
|
||||
z += 1;
|
||||
|
||||
// not recommended on anything other than the very smallest of screens
|
||||
// // show unclaimed portals at an additional zoom level further than by default
|
||||
// if (mapZoom >= 15) z += 1;
|
||||
|
||||
|
||||
// limiting the mazimum zoom level for data retrieval reduces the number of requests at high zoom levels
|
||||
// (as all portal data is retrieved at z=17, why retrieve multiple z=18 tiles when fewer z=17 would do?)
|
||||
// very effective along with the new cache code
|
||||
if (z > 17) z=17;
|
||||
|
||||
// if the data zoom is above the map zoom we can step back if the detail level is the same
|
||||
// with the new cache code this works rather well
|
||||
while (z > mapZoom && getMinPortalLevelForZoom(z) == getMinPortalLevelForZoom(z-1)) {
|
||||
z = z-1;
|
||||
// and, the same scale for L2+ and L3+ portals. again, forcing the level down isn't unfriendly to the servers
|
||||
// (ditto on the cacheing)
|
||||
if (mapZoom >= 12) {
|
||||
return 13;
|
||||
}
|
||||
|
||||
return z;
|
||||
return origGetPortalDataZoom();
|
||||
}
|
||||
|
||||
|
||||
|
256
plugins/update-check.user.js
Normal file
256
plugins/update-check.user.js
Normal file
@ -0,0 +1,256 @@
|
||||
// ==UserScript==
|
||||
// @id iitc-plugin-update-check@jonatkins
|
||||
// @name IITC plugin: Check for updates
|
||||
// @category Misc
|
||||
// @version 0.1.0.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Check for updates for IITC and plugins against http://iitc.jonatkins.com/. Can also report status messages for known IITC issues.
|
||||
// @include https://www.ingress.com/intel*
|
||||
// @include http://www.ingress.com/intel*
|
||||
// @match https://www.ingress.com/intel*
|
||||
// @match http://www.ingress.com/intel*
|
||||
// @grant none
|
||||
// ==/UserScript==
|
||||
|
||||
@@PLUGINSTART@@
|
||||
|
||||
// PLUGIN START ////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// use own namespace for plugin
|
||||
window.plugin.updateCheck = function() {};
|
||||
|
||||
window.plugin.updateCheck.url = 'http://iitc.jonatkins.com/versioncheck.php?build=@@BUILDNAME@@';
|
||||
window.plugin.updateCheck.versionDataLoading = false;
|
||||
|
||||
|
||||
window.plugin.updateCheck.versionCompare = function(a,b) {
|
||||
a = a.split('.');
|
||||
b = b.split('.');
|
||||
|
||||
// adding dummy -1 entries to both split arrays simplifies comparisons
|
||||
a.push(-1);
|
||||
b.push(-1);
|
||||
|
||||
var minlen = Math.min(a.length, b.length);
|
||||
|
||||
for (var i=0; i<minlen; i++) {
|
||||
var anum = parseInt(a[i]);
|
||||
var bnum = parseInt(b[i]);
|
||||
if (anum != bnum) {
|
||||
return bnum-anum;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
window.plugin.updateCheck.loadVersionData = function() {
|
||||
if (!window.plugin.updateCheck.versionDataLoading) {
|
||||
window.plugin.updateCheck.versionDataLoading = true;
|
||||
|
||||
var s = document.createElement('script');
|
||||
s.setAttribute('type','text/javascript');
|
||||
s.setAttribute('src', window.plugin.updateCheck.url+'&callback=window.plugin.updateCheck.versionDataCallback');
|
||||
s.setAttribute('id','update-check-script-tag');
|
||||
document.getElementsByTagName("head")[0].appendChild(s);
|
||||
|
||||
} else {
|
||||
// else we're already loading the script and it hasn't completed - do nothing
|
||||
console.warn('update-check: already loading data - cannot load again');
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.updateCheck.versionDataCallback = function(data) {
|
||||
// data loaded - flag it's not loading any more and remove the script tag
|
||||
window.plugin.updateCheck.versionDataLoading = false;
|
||||
var s = document.getElementById('update-check-script-tag');
|
||||
if (s) {
|
||||
s.parentNode.removeChild(s);
|
||||
}
|
||||
|
||||
window.plugin.updateCheck.showReport(data);
|
||||
}
|
||||
|
||||
window.plugin.updateCheck.versionHTML = function(ver) {
|
||||
var re = new RegExp ('^([0-9]+\\.[0-9]+\\.[0-9]+)(\\.2[0-9][0-9][0-9][01][0-9][0123][0-9]\\.[0-9]+)$');
|
||||
var match = ver.match(re);
|
||||
if (match) {
|
||||
return match[1]+'<small>'+match[2]+'</small>';
|
||||
} else {
|
||||
return ver;
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.updateCheck.compareDetails = function(web_version, script_version) {
|
||||
// compare the local script version data with the website version data
|
||||
// and return an object with the results
|
||||
var result = {};
|
||||
|
||||
result.webUrl = web_version.pageUrl;
|
||||
result.downloadUrl = web_version.downloadUrl;
|
||||
result.webVersion = web_version.version;
|
||||
|
||||
result.localVersion = script_version.script && script_version.script.version;
|
||||
|
||||
if (result.localVersion && result.webVersion) {
|
||||
result.comp = window.plugin.updateCheck.versionCompare (result.localVersion, result.webVersion);
|
||||
|
||||
result.outOfDate = result.comp>0;
|
||||
result.upToDate = result.comp==0;
|
||||
result.localNewer = result.comp<0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
var webVerHTML = result.webVersion && window.plugin.updateCheck.versionHTML(result.webVersion);
|
||||
var localVerHTML = result.localVersion && window.plugin.updateCheck.versionHTML(result.localVersion);
|
||||
|
||||
// var webLinkInstallHTML = '';
|
||||
// if (result.downloadUrl && result.webUrl) {
|
||||
// webLinkInstallHTML = '<a href="'+result.webUrl+'" title="Web page" target="_blank">web</a> '
|
||||
// + '<a href="'+result.downloadUrl+'" title="Install" target="_blank">install</a>';
|
||||
// }
|
||||
|
||||
if (!result.localVersion) {
|
||||
result.html = '<span class="help" title="Your version unknown\nLatest version '+webVerHTML+'">version check failed</span>';
|
||||
} else if (!result.webVersion) {
|
||||
result.html = '<span class="help" title="Your version '+localVerHTML+'\nNo version from update check server">version check failed</span>';
|
||||
} else if (result.upToDate) {
|
||||
result.html = '<span class="help" title="Version '+localVerHTML+'">up to date</span>';
|
||||
} else if (result.outOfDate) {
|
||||
result.html = '<span class="help" title="Your version '+localVerHTML+'\nLatest version '+webVerHTML+'">out of date</span>';
|
||||
} else if (result.localNewer) {
|
||||
result.html = localVerHTML+' is newer than '+webVerHTML+'(?!)';
|
||||
} else {
|
||||
console.warn ('Unknown case of version combinations!');
|
||||
result.html = '<span class="help" title="Your version '+localVerHTML+'\nLatest version '+webVerHTML+'">version check failed(!?)</span>';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
window.plugin.updateCheck.showReport = function(data) {
|
||||
var result = '<b>WORK IN PROGRESS</b>';
|
||||
|
||||
if (data.error) {
|
||||
result += '<div><b>Error checking for updates</b><br>'+data.error+'</div>';
|
||||
} else {
|
||||
if (data.name) {
|
||||
result += '<div>IITC update check: '+data.name+'</div>';
|
||||
}
|
||||
|
||||
if (data.iitc && window.script_info) {
|
||||
var compare = window.plugin.updateCheck.compareDetails(data.iitc, window.script_info);
|
||||
result += '<div>IITC Main script: '+compare.html+'</div>';
|
||||
|
||||
} else {
|
||||
if (!data.iitc) {
|
||||
result += '<div>Warning: no version information for main IITC script found in response</div>';
|
||||
}
|
||||
if (!window.script_info) {
|
||||
result += '<div>Warning: your IITC script does not contain version data</div>';
|
||||
}
|
||||
}
|
||||
|
||||
if (data.plugins && window.bootPlugins) {
|
||||
|
||||
var plugins = { upToDate: [], outOfDate: [], other: [] };
|
||||
|
||||
if (window.bootPlugins.length == 0) {
|
||||
result += '<li>No plugins installed</li>';
|
||||
} else {
|
||||
for (var i=0; i<window.bootPlugins.length; i++) {
|
||||
var pluginStatus = { index: i, status: 'other' };
|
||||
|
||||
var info = window.bootPlugins[i].info;
|
||||
pluginStatus.name = info.script && info.script.name || info.pluginId || ('(unknown plugin index '+i+')');
|
||||
pluginStatus.name = pluginStatus.name.replace ( /^IITC plugin: /i, '' );
|
||||
|
||||
if (info && info.pluginId) {
|
||||
var webinfo = data.plugins[info.pluginId];
|
||||
if (webinfo) {
|
||||
var compare = window.plugin.updateCheck.compareDetails(webinfo,info);
|
||||
pluginStatus.compare = compare;
|
||||
if (compare.upToDate) {
|
||||
pluginStatus.status = 'upToDate';
|
||||
} else if (compare.outOfDate) {
|
||||
pluginStatus.status = 'outOfDate';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugins[pluginStatus.status].push(pluginStatus);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
result += '<div>Plugins:<table>';
|
||||
|
||||
var formatRow = function(p) {
|
||||
var status = p.status;
|
||||
var name = p.name;
|
||||
var statustext = p.compare && p.compare.html || '-';
|
||||
|
||||
return '<tr class="'+status+'"><td>'+name+'</td><td>'+statustext+'</td></tr>';
|
||||
}
|
||||
|
||||
result += '<tr><th colspan="3">Out of date</th></tr>';
|
||||
for (var i in plugins.outOfDate) {
|
||||
result += formatRow (plugins.outOfDate[i]);
|
||||
}
|
||||
if (plugins.outOfDate.length==0) {
|
||||
result += '<tr><td colspan="3">no plugins</td></tr>';
|
||||
}
|
||||
|
||||
result += '<tr><th colspan="3">Up To Date</th></tr>';
|
||||
for (var i in plugins.upToDate) {
|
||||
result += formatRow (plugins.upToDate[i]);
|
||||
}
|
||||
if (plugins.upToDate.length==0) {
|
||||
result += '<tr><td colspan="3">no plugins</td></tr>';
|
||||
}
|
||||
|
||||
result += '<tr><th colspan="3">Other</th></tr>';
|
||||
for (var i in plugins.other) {
|
||||
result += formatRow (plugins.other[i]);
|
||||
}
|
||||
if (plugins.other.length==0) {
|
||||
result += '<tr><td colspan="3">no plugins</td></tr>';
|
||||
}
|
||||
|
||||
result += '</table</div>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dialog({
|
||||
width: 700,
|
||||
title: 'Update check',
|
||||
html: result
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
window.plugin.updateCheck.open = function() {
|
||||
|
||||
// TODO? open a dialog/show a message indicating that the update check is in progress, before the data is loaded?
|
||||
// TODO? prevent loading the version data every time - cache it, with a user option to force fresh data
|
||||
|
||||
window.plugin.updateCheck.loadVersionData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
window.plugin.updateCheck.setup = function() {
|
||||
$('#toolbox').append(' <a onclick="window.plugin.updateCheck.open()" title="Check for IITC updates">Update check</a>');
|
||||
};
|
||||
|
||||
var setup = window.plugin.updateCheck.setup;
|
||||
|
||||
// PLUGIN END //////////////////////////////////////////////////////////
|
||||
|
||||
@@PLUGINEND@@
|
@ -102,8 +102,14 @@
|
||||
window.plugin.zaprange.zapLayerEnlHolderGroup.addLayer(window.plugin.zaprange.zapCircleEnlHolderGroup);
|
||||
window.plugin.zaprange.zapLayerResHolderGroup.addLayer(window.plugin.zaprange.zapCircleResHolderGroup);
|
||||
|
||||
window.addLayerGroup('Zaprange Enlightened', window.plugin.zaprange.zapLayerEnlHolderGroup, true);
|
||||
window.addLayerGroup('Zaprange Resistance', window.plugin.zaprange.zapLayerResHolderGroup, true);
|
||||
// to avoid any favouritism, we'll put the player's own faction layer first
|
||||
if (PLAYER.team == 'RESISTANCE') {
|
||||
window.addLayerGroup('Zaprange Resistance', window.plugin.zaprange.zapLayerResHolderGroup, true);
|
||||
window.addLayerGroup('Zaprange Enlightened', window.plugin.zaprange.zapLayerEnlHolderGroup, true);
|
||||
} else {
|
||||
window.addLayerGroup('Zaprange Enlightened', window.plugin.zaprange.zapLayerEnlHolderGroup, true);
|
||||
window.addLayerGroup('Zaprange Resistance', window.plugin.zaprange.zapLayerResHolderGroup, true);
|
||||
}
|
||||
|
||||
window.addHook('portalAdded', window.plugin.zaprange.portalAdded);
|
||||
|
||||
|
32
style.css
32
style.css
@ -9,7 +9,7 @@ html, body, #map {
|
||||
|
||||
body {
|
||||
font-size: 14px;
|
||||
font-family: "roboto",arial,helvetica,sans-serif;
|
||||
font-family: "Roboto", "Helvetica Neue", Helvetica, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ a:hover {
|
||||
.fieldmu {
|
||||
color: #FFCE00;
|
||||
font-size: 13px;
|
||||
font-family: "roboto",arial,helvetica,sans-serif; /*override leaflet-container */
|
||||
font-family: Roboto, "Helvetica Neue", Helvetica, sans-serif; /*override leaflet-container */
|
||||
text-align: center;
|
||||
text-shadow: 0 0 0.2em black, 0 0 0.2em black, 0 0 0.2em black;
|
||||
pointer-events: none;
|
||||
@ -210,6 +210,7 @@ a:hover {
|
||||
z-index: 3000;
|
||||
background: rgba(8, 48, 78, 0.9);
|
||||
font-size: 12.6px;
|
||||
line-height: 15px;
|
||||
color: #eee;
|
||||
border: 1px solid #20A8B1;
|
||||
border-bottom: 0;
|
||||
@ -255,7 +256,6 @@ em {
|
||||
}
|
||||
|
||||
#chat td, #chatinput td {
|
||||
font-family: Verdana, sans-serif;
|
||||
font-size: 12.6px;
|
||||
vertical-align: top;
|
||||
padding-bottom: 3px;
|
||||
@ -302,7 +302,6 @@ mark {
|
||||
summary {
|
||||
color: #bbb;
|
||||
display: inline-block;
|
||||
font-family: Verdana,sans-serif;
|
||||
height: 16px;
|
||||
overflow: hidden;
|
||||
padding: 0 2px;
|
||||
@ -333,7 +332,6 @@ summary {
|
||||
#chatinput input {
|
||||
background: transparent;
|
||||
font-size: 12.6px;
|
||||
font-family: Verdana,sans-serif;
|
||||
color: #EEEEEE;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -384,6 +382,7 @@ h2 {
|
||||
}
|
||||
|
||||
h2 #name {
|
||||
font-weight: 300;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@ -472,6 +471,12 @@ input {
|
||||
margin-bottom: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search_not_found{
|
||||
color:red;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
::-webkit-input-placeholder {
|
||||
font-style: italic;
|
||||
}
|
||||
@ -511,6 +516,7 @@ h3 {
|
||||
background-size: contain;
|
||||
cursor: help;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.imgpreview img.hide {
|
||||
@ -527,6 +533,7 @@ h3 {
|
||||
display: block;
|
||||
margin-right: 15px;
|
||||
text-align:right;
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* portal mods */
|
||||
@ -697,7 +704,6 @@ h3 {
|
||||
right: 2px;
|
||||
cursor: pointer;
|
||||
color: #FFCE00;
|
||||
font-family: "Arial", sans;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@ -742,7 +748,8 @@ h3 {
|
||||
background-color: rgba(8, 48, 78, 0.9);
|
||||
border: 1px solid #20A8B1;
|
||||
color: #eee;
|
||||
font: 13px/15px Roboto, Arial, Helvetica, sans-serif;
|
||||
font-size: 13px;
|
||||
line-height: 15px;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
@ -783,6 +790,8 @@ h3 {
|
||||
}
|
||||
|
||||
.ui-dialog-titlebar {
|
||||
font-size: 13px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
background-color: rgba(8, 60, 78, 0.9);
|
||||
@ -892,7 +901,6 @@ td + td {
|
||||
/* redeem results *****************************************************/
|
||||
.redeem-result-table {
|
||||
font-size: 14px;
|
||||
font-family: Roboto, Arial, Helvetica, sans-serif;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
@ -943,13 +951,12 @@ td + td {
|
||||
color: #28f428;
|
||||
}
|
||||
|
||||
#portal_highlight_select{
|
||||
#portal_highlight_select {
|
||||
position: absolute;
|
||||
top:5px;
|
||||
left:10px;
|
||||
z-index: 2500;
|
||||
font-size:11px;
|
||||
font-family: "roboto",arial,helvetica,sans-serif;
|
||||
background-color:#0E3C46;
|
||||
color:#ffce00;
|
||||
|
||||
@ -970,3 +977,8 @@ td + td {
|
||||
.portal_details tr.padding-top th, .portal_details tr.padding-top td {
|
||||
padding-top: 0.7em;
|
||||
}
|
||||
|
||||
#play_button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ function loadPopularity()
|
||||
{
|
||||
$items = explode ( ' ', $line );
|
||||
$popularity[$items[0]] = (int)$items[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $popularity;
|
||||
@ -33,10 +33,10 @@ function loadPopularity()
|
||||
|
||||
function popularity_cmp ( $a, $b )
|
||||
{
|
||||
if ( $a['popularity'] == $b['popularity'] )
|
||||
if ( @$a['popularity'] == @$b['popularity'] )
|
||||
return 0;
|
||||
// sort from highest to lowest
|
||||
return ($a['popularity'] > $b['popularity']) ? -1 : 1;
|
||||
return (@$a['popularity'] > @$b['popularity']) ? -1 : 1;
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,6 @@ Yes it is!
|
||||
</ul>
|
||||
Note:
|
||||
<ul>
|
||||
<li>The plugins wrapper function has to be identical to all other IITC plugins (IITCm removes it via search and replace).
|
||||
Alternatively, you can use the @@PLUGINSTART@@ / @@PLUGINEND@@ macros or remove the wrapper by hand.</li>
|
||||
<li>The filename has to end with *.user.js.</li>
|
||||
<li>If you don't know where to find your home directory: Enable dev-mode in the settings and follow the hint.</li>
|
||||
</ul>
|
||||
|
@ -13,39 +13,37 @@ offers many more features. It is available for
|
||||
|
||||
<h3>Latest news</h3>
|
||||
|
||||
<h4>22nd September 2013</h4>
|
||||
<h4>29th October 2013</h4>
|
||||
<p>
|
||||
<b>Update</b>: IITC Mobile 0.6.5 replaces 0.6.4. This fixes a crash on entering plugin preferences on some tablets.
|
||||
IITC 0.14.4 and IITC Mobile 0.7.7 have just been released. A critical update required to work with changes made to the
|
||||
standard intel site. Changes include
|
||||
<ul>
|
||||
<li>Fix to geodesic circle drawing. They were not correctly distorted, leading to incorrect link ranges drawn on the map.</li>
|
||||
<li>Bookmarks plugin: add layer and highlighter to indicate bookmarked portals</li>
|
||||
<li>Player tracker plugin: markers fade for older activity, and separate layers for each faction</li>
|
||||
<li>The 'About IITC' dialog now lists which plugins are installed. This may not work correctly for 3rd party plugins at this time</li>
|
||||
<li>Mobile:
|
||||
<ul>
|
||||
<li>Custom fullscreen preferences</li>
|
||||
<li>Install to SD Card</li>
|
||||
<li>Cache move to SD card option (hence the new permissions)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>... and, as always, various bugfixes and improvements.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
IITC 0.14.1 and IITC Mobile 0.6.4 have been released. Changes in this version include:
|
||||
<ul>
|
||||
<li>Better performance when a very large number of portals are within view (country/continent level)</li>
|
||||
<li>Add layer chooser options to hide resistance/enlightened portals/links/fields</li>
|
||||
<li>Chat tab now remembers which was active when reloading IITC</li>
|
||||
<li>Fix some shorter links not showing on the map</li>
|
||||
<li>Add details of hack information (number/cooldown time, taking account of mods) and mitigation (from shields and links)
|
||||
to the portal information panel</li>
|
||||
<li>Mobile
|
||||
<ul>
|
||||
<li>increase the size of various links on the info page to make them easier to tap</li>
|
||||
<li>move the highlight selection dropdown to the native android app bar at the top</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
And plugins:
|
||||
<ul>
|
||||
<li>Major update to bookmarks-by-zaso, including sync support</li>
|
||||
<li>New features added to the resonators plugin</li>
|
||||
<li>max-links plugin - start of rename to 'tidy links' - as this is a better description of what it does</li>
|
||||
<li>show-linked-portals - indicate which are incoming/outgoing links in the tooltip</li>
|
||||
<li>New Plugins
|
||||
<ul>
|
||||
<li>show-link-direction, to indicate visually which portal a link was created from</li>
|
||||
<li>highlighter for portal mitigation - to show strength of defence from shields and links at a glance</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
And, as always, numerous other bug fixes, tweaks and improvements.
|
||||
<b>3RD PARTY PLUGIN AUTHORS</b>: The plugin wrapper code has been modified to pass through the additioal version
|
||||
information. While existing plugins should continue to work, I highly recommend updating the wrapper code in your
|
||||
scripts to match.
|
||||
</p>
|
||||
|
||||
<h4>16th October 2013</h4>
|
||||
<p>
|
||||
IITC 0.14.3 and IITC MObile 0.7.4 have just been released. This is a critical update required to work with the latest
|
||||
changes Niantic have made to the standard intel site. Additionally, the draw-tools plugin now snaps points to portals
|
||||
when creating lines/polygons/markers (was actually in 0.14.2 release), a bugfix relating to IITC not realising who
|
||||
'you' are, causing some highlighters to break, and a handful of other tweaks/bugfixes.
|
||||
</p>
|
||||
|
||||
<a class="btn btn-small" href="?page=news">Older news</a>
|
||||
|
@ -1,5 +1,49 @@
|
||||
<h2>News</h2>
|
||||
|
||||
<h4>29th October 2013</h4>
|
||||
<p>
|
||||
IITC 0.14.4 and IITC Mobile 0.7.7 have just been released. A critical update required to work with changes made to the
|
||||
standard intel site. Changes include
|
||||
<ul>
|
||||
<li>Fix to geodesic circle drawing. They were not correctly distorted, leading to incorrect link ranges drawn on the map.</li>
|
||||
<li>Bookmarks plugin: add layer and highlighter to indicate bookmarked portals</li>
|
||||
<li>Player tracker plugin: markers fade for older activity, and separate layers for each faction</li>
|
||||
<li>The 'About IITC' dialog now lists which plugins are installed. This may not work correctly for 3rd party plugins at this time</li>
|
||||
<li>Mobile:
|
||||
<ul>
|
||||
<li>Custom fullscreen preferences</li>
|
||||
<li>Install to SD Card</li>
|
||||
<li>Cache move to SD card option (hence the new permissions)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>... and, as always, various bugfixes and improvements.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<b>3RD PARTY PLUGIN AUTHORS</b>: The plugin wrapper code has been modified to pass through the additioal version
|
||||
information. While existing plugins should continue to work, I highly recommend updating the wrapper code in your
|
||||
scripts to match.
|
||||
</p>
|
||||
|
||||
<h4>16th October 2013</h4>
|
||||
<p>
|
||||
IITC 0.14.3 and IITC MObile 0.7.4 have just been released. This is a critical update required to work with the latest
|
||||
changes Niantic have made to the standard intel site. Additionally, the draw-tools plugin now snaps points to portals
|
||||
when creating lines/polygons/markers (was actually in 0.14.2 release), a bugfix relating to IITC not realising who
|
||||
'you' are, causing some highlighters to break, and a handful of other tweaks/bugfixes.
|
||||
</p>
|
||||
|
||||
<h4>1st October 2013</h4>
|
||||
<p>
|
||||
IITC 0.14.2 and IITC Mobile 0.7.1 have been released. This is a critical update required to work with changes made
|
||||
to the standard intel site. Additionally, a major update to the mobile app interface has been made, and a handful
|
||||
of tweaks and bugfixes to IITC and a few plugins.
|
||||
</p>
|
||||
<p>
|
||||
The standard intel site now includes an 'alerts' chat tab. This will be coming to IITC in the future, but it's
|
||||
better to get this working version released without it than hold things up just for that.
|
||||
</p>
|
||||
|
||||
<h4>22nd September 2013</h4>
|
||||
<p>
|
||||
<b>Update</b>: IITC Mobile 0.6.5 replaces 0.6.4. This fixes a crash on entering plugin preferences on some tablets.
|
||||
|
107
website/versioncheck.php
Normal file
107
website/versioncheck.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
include_once "code/userscript.php";
|
||||
include_once "code/url/url_to_absolute.php";
|
||||
|
||||
|
||||
$response = Array();
|
||||
|
||||
|
||||
$build = $_REQUEST['build'];
|
||||
|
||||
|
||||
$details = Array (
|
||||
'jonatkins' => Array ( # live release
|
||||
'path' => 'release',
|
||||
'name' => 'Stable release build',
|
||||
'web' => 'http://iitc.jonatkins.com/?page=download',
|
||||
),
|
||||
'jonatkins-test' => Array ( # public test builds
|
||||
'path' => 'test',
|
||||
'name' => 'Test build',
|
||||
'web' => 'http://iitc.jonatkins.com/?page=test',
|
||||
),
|
||||
|
||||
'jonatkins-experimental' => Array ( # rarely used, for features not quite ready for 'test'
|
||||
'path' => 'experimental',
|
||||
'name' => 'Experimental build',
|
||||
'web' => 'http://iitc.jonatkins.com/?page=test&build=experimental',
|
||||
),
|
||||
|
||||
'jonatkins-dev' => Array ( # personal
|
||||
'path' => 'dev',
|
||||
'name' => 'Development builds - not for public use',
|
||||
'web' => 'http://iitc.jonatkins.com/?page=test&build=dev',
|
||||
),
|
||||
|
||||
'local' => Array ( # not a real build, but often the default for local development
|
||||
'path' => NULL,
|
||||
'name' => 'Local build - no update check available',
|
||||
),
|
||||
);
|
||||
|
||||
if ( array_key_exists ( $build, $details ) )
|
||||
{
|
||||
$info = $details[$build];
|
||||
|
||||
$pageurl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] ? "https" : "http")."://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
||||
|
||||
$response['name'] = $info['name'];
|
||||
|
||||
$dir = $info['path'];
|
||||
|
||||
// load main script version
|
||||
$iitc_details = loadUserScriptHeader ( "$dir/total-conversion-build.user.js" );
|
||||
$response['iitc'] = Array (
|
||||
'version' => $iitc_details['@version'],
|
||||
'downloadUrl' => url_to_absolute ( $pageurl, "$dir/total-conversion-build.user.js" ),
|
||||
'pageUrl' => url_to_absolute ( $pageurl, $info['web'] ),
|
||||
);
|
||||
|
||||
// and now the plugins
|
||||
|
||||
$response['plugins'] = Array();
|
||||
|
||||
foreach ( glob ( "$dir/plugins/*.user.js" ) as $path )
|
||||
{
|
||||
$basename = basename ( $path, ".user.js" );
|
||||
$details = loadUserScriptHeader ( $path );
|
||||
|
||||
$response['plugins'][$basename] = Array (
|
||||
'version' => $details['@version'],
|
||||
'downloadUrl' => url_to_absolute ( $pageurl, "$dir/plugins/$basename.user.js" ),
|
||||
'pageUrl' => url_to_absolute ( $pageurl, $info['web']."#plugin-$basename" ),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$response['error'] = 'Unsupported build for version check';
|
||||
}
|
||||
|
||||
|
||||
$data = json_encode ( $response );
|
||||
|
||||
|
||||
# send the response - allow either jsonp (using a 'callback' parameter), or regular json
|
||||
if ( array_key_exists ( 'callback', $_GET ) )
|
||||
{
|
||||
header('Content-Type: text/javascript; charset=utf8');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Access-Control-Max-Age: 3628800');
|
||||
header('Access-Control-Allow-Methods: GET, POST');
|
||||
|
||||
$callback = $_GET['callback'];
|
||||
echo $callback.'('.$data.');';
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal JSON string
|
||||
header('Content-Type: application/json; charset=utf8');
|
||||
|
||||
echo $data;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user