Merge branch 'master' into release

This commit is contained in:
Jon Atkins 2014-04-29 04:37:15 +01:00
commit 13da501548
35 changed files with 904 additions and 351 deletions

View File

@ -78,6 +78,21 @@ window.setupLayerChooserStatusRecorder = function() {
});
}
window.layerChooserSetDisabledStates = function() {
// layer selector - enable/disable layers that aren't visible due to zoom level
var minlvl = getMinPortalLevel();
var portalSelection = $('.leaflet-control-layers-overlays label');
//it's an array - 0=unclaimed, 1=lvl 1, 2=lvl 2, ..., 8=lvl 8 - 9 relevant entries
//mark all levels below (but not at) minlvl as disabled
portalSelection.slice(0, minlvl).addClass('disabled').attr('title', 'Zoom in to show those.');
//and all from minlvl to 8 as enabled
portalSelection.slice(minlvl, 8+1).removeClass('disabled').attr('title', '');
//TODO? some generic mechanism where other layers can have their disabled state marked on/off? a few
//plugins have code to do it by hand already
}
window.setupStyles = function() {
$('head').append('<style>' +
[ '#largepreview.enl img { border:2px solid '+COLORS[TEAM_ENL]+'; } ',
@ -137,7 +152,9 @@ window.setupMap = function() {
center: [0,0],
zoom: 1,
zoomControl: (typeof android !== 'undefined' && android && android.showZoom) ? android.showZoom() : true,
minZoom: 1
minZoom: 1,
// zoomAnimation: false,
markerZoomAnimation: false
});
// add empty div to leaflet control areas - to force other leaflet controls to move around IITC UI elements
@ -279,6 +296,9 @@ window.setupMap = function() {
map.on('movestart', function() { window.mapRunsUserAction = true; window.requests.abort(); window.startRefreshTimeout(-1); });
map.on('moveend', function() { window.mapRunsUserAction = false; window.startRefreshTimeout(ON_MOVE_REFRESH*1000); });
map.on('zoomend', function() { window.layerChooserSetDisabledStates(); });
window.layerChooserSetDisabledStates();
// on zoomend, check to see the zoom level is an int, and reset the view if not
// (there's a bug on mobile where zoom levels sometimes end up as fractional levels. this causes the base map to be invisible)
map.on('zoomend', function() {
@ -353,20 +373,20 @@ window.setMapBaseLayer = function() {
// included as inline script in the original site, the data is static
// and cannot be updated.
window.setupPlayerStat = function() {
var level;
// stock site updated to supply the actual player level, AP requirements and XM capacity values
var level = PLAYER.verified_level;
PLAYER.level = level; //for historical reasons IITC expects PLAYER.level to contain the current player level
var ap = parseInt(PLAYER.ap);
for(level = 0; level < MIN_AP_FOR_LEVEL.length; level++) {
if(ap < MIN_AP_FOR_LEVEL[level]) break;
}
PLAYER.level = level;
var thisLvlAp = parseInt(PLAYER.min_ap_for_current_level);
var nextLvlAp = parseInt(PLAYER.min_ap_for_next_level);
var thisLvlAp = MIN_AP_FOR_LEVEL[level-1];
var nextLvlAp = MIN_AP_FOR_LEVEL[level] || ap;
var lvlUpAp = digits(nextLvlAp-ap);
var lvlApProg = Math.round((ap-thisLvlAp)/(nextLvlAp-thisLvlAp)*100);
if (nextLvlAp) {
var lvlUpAp = digits(nextLvlAp-ap);
var lvlApProg = Math.round((ap-thisLvlAp)/(nextLvlAp-thisLvlAp)*100);
} // else zero nextLvlAp - so at maximum level(?)
var xmMax = MAX_XM_PER_LEVEL[level];
var xmMax = parseInt(PLAYER.xm_capacity);
var xmRatio = Math.round(PLAYER.energy/xmMax*100);
var cls = PLAYER.team === 'RESISTANCE' ? 'res' : 'enl';
@ -375,7 +395,7 @@ window.setupPlayerStat = function() {
var t = 'Level:\t' + level + '\n'
+ 'XM:\t' + PLAYER.energy + ' / ' + xmMax + '\n'
+ 'AP:\t' + digits(ap) + '\n'
+ (level < 8 ? 'level up in:\t' + lvlUpAp + ' AP' : 'Congrats! (neeeeerd)')
+ (nextLvlAp > 0 ? 'level up in:\t' + lvlUpAp + ' AP' : 'Maximul level reached(!)')
+ '\n\Invites:\t'+PLAYER.available_invites
+ '\n\nNote: your player stats can only be updated by a full reload (F5)';
@ -387,7 +407,7 @@ window.setupPlayerStat = function() {
+ '</div>'
+ '<div id="stats">'
+ '<sup>XM: '+xmRatio+'%</sup>'
+ '<sub>' + (level < 8 ? 'level: '+lvlApProg+'%' : 'max level') + '</sub>'
+ '<sub>' + (nextLvlAp > 0 ? 'level: '+lvlApProg+'%' : 'max level') + '</sub>'
+ '</div>'
+ '</h2>'
);
@ -520,7 +540,6 @@ window.setupLayerChooserApi = function() {
// BOOTING ///////////////////////////////////////////////////////////
function boot() {
try { //EXPERIMENTAL TEST
if(!isSmartphone()) // TODO remove completely?
window.debug.console.overwriteNativeIfRequired();
@ -530,17 +549,13 @@ function boot() {
var iconDefImage = '@@INCLUDEIMAGE:images/marker-icon.png@@';
var iconDefRetImage = '@@INCLUDEIMAGE:images/marker-icon-2x.png@@';
var iconShadowImage = '@@INCLUDEIMAGE:images/marker-shadow.png@@';
L.Icon.Default = L.Icon.extend({options: {
iconUrl: iconDefImage,
iconRetinaUrl: iconDefRetImage,
shadowUrl: iconShadowImage,
shadowRetinaUrl: iconShadowImage,
iconSize: new L.Point(25, 41),
iconAnchor: new L.Point(12, 41),
popupAnchor: new L.Point(1, -34),
shadowSize: new L.Point(41, 41)
}});
window.setupIdle();
@ -644,20 +659,13 @@ function boot() {
android.bootFinished();
}
//EXPERIMENTAL TEST
} catch(e) {
console.log('Exception caught in IITC boot function - will fail to start');
console.log(e);
debugger;
throw e;
}
}
@@INCLUDERAW:external/load.js@@
try { console.log('Loading included JS now'); } catch(e) {}
@@INCLUDERAW:external/leaflet.js@@
@@INCLUDERAW:external/leaflet-src.js@@
@@INCLUDERAW:external/L.Geodesic.js@@
// modified version of https://github.com/shramov/leaflet-plugins. Also
// contains the default Ingress map style.

View File

@ -41,9 +41,7 @@ window.chat._oldBBox = null;
window.chat.genPostData = function(isFaction, storageHash, getOlderMsgs) {
if(typeof isFaction !== 'boolean') throw('Need to know if public or faction chat.');
// get window bounds, and extend to the minimum chat radius
chat._localRangeCircle.setLatLng(map.getCenter());
var b = map.getBounds().extend(chat._localRangeCircle.getBounds());
var b = map.getBounds();
// set a current bounding box if none set so far
if (!chat._oldBBox) chat._oldBBox = b;
@ -574,8 +572,6 @@ window.chat.keepScrollPosition = function(box, scrollBefore, isOldMsgs) {
//
window.chat.setup = function() {
window.chat._localRangeCircle = L.circle(map.getCenter(), CHAT_MIN_RANGE*1000);
if (localStorage['iitc-chat-tab']) {
var t = $('<a>'+localStorage['iitc-chat-tab']+'</a>');
window.chat.chooseAnchor(t);

View File

@ -17,16 +17,21 @@ window.updateGameScore = function(data) {
// to detect the problem and try a different set is easiest in a place where there's only a single request of that type
// sent at once, and it has no extra parameters. this method matches those requirements
if (data.error || (data.indexOf && data.indexOf('"error"') != -1)) {
window.updateGameScoreFailCount++;
if (window.updateGameScoreFailCount <= window.requestParameterMunges.length) {
//TODO: methods to try a different munge set?
// window.activeRequestMungeSet = (window.activeRequestMungeSet+1) % window.requestParameterMunges.length;
// console.warn('IITC munge issue - cycling to set '+window.activeRequestMungeSet);
updateGameScore();
if (data.error == 'missing version') {
dialog({
title: 'Reload IITC',
html: '<p>IITC is using an outdated munge set. This can happen when Niantic update the standard intel site.</p>'
+'<p>You need to reload the page to get the updated changes.</p>'
+'<p>If you have just reloaded the page, then an old version of the standard site script is cached somewhere.'
+'In this case, try clearing your cache, or waiting 15-30 minutes for the stale data to expire.</p>',
buttons: {
'RELOAD': function() { window.location.reload(); }
}
});
return;
} else {
console.error('IITC munge issue - and retry limit reached. IITC will likely fail');
console.error('game score failed to load');
}
}

View File

@ -24,7 +24,7 @@ window.getMapZoomTileParameters = function(zoom) {
} catch(e) {
console.warn(e);
// known correct as of 2014-03-14
// known correct as of 2014-03-19
ZOOM_TO_TILES_PER_EDGE = [32, 32, 32, 32, 256, 256, 256, 1024, 1024, 1536, 4096, 4096, 6500, 6500, 6500];
MAX_TILES_PER_EDGE = 9000;
ZOOM_TO_LEVEL = [8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1, 1];

View File

@ -3,7 +3,7 @@
window.RenderDebugTiles = function() {
this.CLEAR_CHECK_TIME = 0.25;
this.CLEAR_CHECK_TIME = L.Path.CANVAS ? 2.0 : 0.5;
this.FADE_TIME = 2.0;
this.debugTileLayer = L.layerGroup();
@ -57,6 +57,7 @@ window.RenderDebugTiles.prototype.setState = function(id,state) {
case 'request-fail': col='#a00'; fill='#666'; break;
case 'tile-fail': col='#f00'; fill='#666'; break;
case 'tile-timeout': col='#ff0'; fill='#666'; break;
case 'render-queue': col='#f0f'; fill='#f0f'; break;
}
this.setColour (id, col, fill);
if (clearDelay >= 0) {
@ -72,8 +73,11 @@ window.RenderDebugTiles.prototype.setState = function(id,state) {
window.RenderDebugTiles.prototype.startTimer = function(waitTime) {
var _this = this;
if (!this.timer) {
this.timer = setTimeout ( function() { _this.timer = undefined; _this.runClearPass(); }, waitTime );
if (!_this.timer) {
// a timeout of 0 firing the actual timeout - helps things run smoother
_this.timer = setTimeout ( function() {
_this.timer = setTimeout ( function() { _this.timer = undefined; _this.runClearPass(); }, waitTime );
}, 0);
}
}

View File

@ -10,15 +10,16 @@ window.Render = function() {
this.CLUSTER_SIZE = L.Browser.mobile ? 16 : 8; // the map is divided into squares of this size in pixels for clustering purposes. mobile uses larger markers, so therefore larger clustering areas
this.CLUSTER_PORTAL_LIMIT = 4; // no more than this many portals are drawn in each cluster square
this.entityVisibilityZoom = undefined;
// link length, in pixels, to be visible. use the portal cluster size, as shorter than this is likely hidden
// under the portals
this.LINK_VISIBLE_PIXEL_LENGTH = this.CLUSTER_SIZE;
this.portalMarkerScale = undefined;
}
// start a render pass. called as we start to make the batch of data requests to the servers
window.Render.prototype.startRenderPass = function() {
window.Render.prototype.startRenderPass = function(level,bounds) {
this.isRendering = true;
this.deletedGuid = {}; // object - represents the set of all deleted game entity GUIDs seen in a render pass
@ -26,6 +27,16 @@ window.Render.prototype.startRenderPass = function() {
this.seenPortalsGuid = {};
this.seenLinksGuid = {};
this.seenFieldsGuid = {};
this.bounds = bounds;
this.clearPortalsBelowLevel(level);
this.resetPortalClusters();
this.resetLinkVisibility();
this.rescalePortalMarkers();
}
window.Render.prototype.clearPortalsBelowLevel = function(level) {
@ -41,40 +52,6 @@ window.Render.prototype.clearPortalsBelowLevel = function(level) {
console.log('Render: deleted '+count+' portals by level');
}
window.Render.prototype.clearEntitiesOutsideBounds = function(bounds) {
var pcount=0, lcount=0, fcount=0;
for (var guid in window.portals) {
var p = portals[guid];
if (!bounds.contains (p.getLatLng()) && guid !== selectedPortal && !artifact.isInterestingPortal(guid)) {
this.deletePortalEntity(guid);
pcount++;
}
}
for (var guid in window.links) {
var l = links[guid];
if (!bounds.intersects (l.getBounds())) {
this.deleteLinkEntity(guid);
lcount++;
}
}
for (var guid in window.fields) {
var f = fields[guid];
if (!bounds.intersects (f.getBounds())) {
this.deleteFieldEntity(guid);
fcount++;
}
}
console.log('Render: deleted '+pcount+' portals, '+lcount+' links, '+fcount+' fields by bounds check');
}
// TODO? as well as clearing portals by level, and clearing entities outside the bounds...
// can we clear unneeded 'fake' links after zooming out? based on the portals no longer being available to construct
// the data? (not *required* - as they'll be removed in the endRenderPass code - but clearing things earlier rather than
// later is preferred, if possible)
// process deleted entity list and entity data
window.Render.prototype.processTileData = function(tiledata) {
@ -167,7 +144,6 @@ window.Render.prototype.endRenderPass = function() {
}
window.Render.prototype.bringPortalsToFront = function() {
return;
for (var lvl in portalsFactionLayers) {
// portals are stored in separate layers per faction
// to avoid giving weight to one faction or another, we'll push portals to front based on GUID order
@ -396,25 +372,23 @@ window.Render.prototype.createLinkEntity = function(ent,faked) {
window.links[ent[0]] = poly;
linksFactionLayers[poly.options.team].addLayer(poly);
// only add the link to the layer if it's long enough to be seen
if (this.linkVisible(poly)) {
linksFactionLayers[poly.options.team].addLayer(poly);
}
}
window.Render.prototype.updateEntityVisibility = function() {
if (this.entityVisibilityZoom === undefined || this.entityVisibilityZoom != map.getZoom()) {
this.entityVisibilityZoom = map.getZoom();
window.Render.prototype.rescalePortalMarkers = function() {
if (this.portalMarkerScale === undefined || this.portalMarkerScale != portalMarkerScale()) {
this.portalMarkerScale = portalMarkerScale();
this.resetPortalClusters();
console.log('Render: map zoom '+map.getZoom()+' changes portal scale to '+portalMarkerScale()+' - redrawing all portals');
if (this.portalMarkerScale === undefined || this.portalMarkerScale != portalMarkerScale()) {
this.portalMarkerScale = portalMarkerScale();
console.log('Render: map zoom '+map.getZoom()+' changes portal scale to '+portalMarkerScale()+' - redrawing all portals');
//NOTE: we're not calling this because it resets highlights - we're calling it as it resets the style (inc size) of all portal markers
resetHighlightedPortals();
}
//NOTE: we're not calling this because it resets highlights - we're calling it as it
// resets the style (inc size) of all portal markers, applying the new scale
resetHighlightedPortals();
}
}
@ -452,7 +426,7 @@ window.Render.prototype.resetPortalClusters = function() {
var guid = c[i];
var p = window.portals[guid];
var layerGroup = portalsFactionLayers[parseInt(p.options.level)][p.options.team];
if (i<this.CLUSTER_PORTAL_LIMIT || p.options.guid == selectedPortal || artifact.isInterestingPortal(p.options.guid)) {
if ((i<this.CLUSTER_PORTAL_LIMIT || p.options.guid == selectedPortal || artifact.isInterestingPortal(p.options.guid)) && this.bounds.contains(p.getLatLng())) {
if (!layerGroup.hasLayer(p)) {
layerGroup.addLayer(p);
}
@ -479,7 +453,9 @@ window.Render.prototype.addPortalToMapLayer = function(portal) {
// however, it won't make a lot of visible difference compared to just pushing to the end of the list, then
// adding to the visible layer if the list is below the limit
if (this.portalClusters[cid].length < this.CLUSTER_PORTAL_LIMIT || portal.options.guid == selectedPortal || artifact.isInterestingPortal(portal.options.guid)) {
portalsFactionLayers[parseInt(portal.options.level)][portal.options.team].addLayer(portal);
if (this.bounds.contains(portal.getLatLng())) {
portalsFactionLayers[parseInt(portal.options.level)][portal.options.team].addLayer(portal);
}
}
}
@ -495,7 +471,7 @@ window.Render.prototype.removePortalFromMapLayer = function(portal) {
var index = this.portalClusters[cid].indexOf(portal.options.guid);
if (index >= 0) {
this.portalClusters[cid].splice(index,1);
// FIXME? if this portal was in on the screen (in the first 10), and we still have 10+ portals, add the new 10to to the screen?
// FIXME? if this portal was in on the screen (in the first 10), and we still have 10+ portals, add the new 10th to the screen?
}
}
}
@ -512,3 +488,50 @@ window.Render.prototype.getPortalClusterID = function(portal) {
}
window.Render.prototype.linkVisible = function(link) {
if (!this.bounds.intersects(link.getBounds())) {
return false;
}
var lengthSquared = this.getLinkPixelLengthSquared (link);
return lengthSquared >= this.LINK_VISIBLE_PIXEL_LENGTH*this.LINK_VISIBLE_PIXEL_LENGTH;
}
window.Render.prototype.resetLinkVisibility = function() {
for (var guid in window.links) {
var link = window.links[guid];
var visible = this.linkVisible(link);
if (visible) {
if (!linksFactionLayers[link.options.team].hasLayer(link)) linksFactionLayers[link.options.team].addLayer(link);
} else {
if (linksFactionLayers[link.options.team].hasLayer(link)) linksFactionLayers[link.options.team].removeLayer(link);
}
}
}
window.Render.prototype.getLinkPixelLengthSquared = function(link) {
var z = map.getZoom();
var latLngs = link.getLatLngs();
if (latLngs.length != 2) {
console.warn ('Link had '+latLngs.length+' points - expected 2!');
return undefined;
}
var point0 = map.project(latLngs[0]);
var point1 = map.project(latLngs[1]);
var dx = point0.x - point1.x;
var dy = point0.y - point1.y;
var lengthSquared = (dx*dx)+(dy*dy);
return lengthSquared;
}

View File

@ -12,6 +12,10 @@ window.MapDataRequest = function() {
this.activeRequestCount = 0;
this.requestedTiles = {};
this.renderQueue = [];
this.renderQueueTimer = undefined;
this.renderQueuePaused = false;
this.idle = false;
@ -27,30 +31,37 @@ window.MapDataRequest = function() {
this.MAX_TILE_RETRIES = 2;
// refresh timers
this.MOVE_REFRESH = 1; //time, after a map move (pan/zoom) before starting the refresh processing
this.MOVE_REFRESH = 3; //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
this.DOWNLOAD_DELAY = 1; //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.
// this gives a chance of other requests finishing, allowing better grouping of retries in new requests
this.RUN_QUEUE_DELAY = 0.5;
this.RUN_QUEUE_DELAY = 0.2;
// delay before requeuing tiles in failed requests
this.BAD_REQUEST_REQUEUE_DELAY = 10; // longer delay before retrying a completely failed request - as in this case the servers are struggling
// delay before processing the queue after failed requests
this.BAD_REQUEST_RUN_QUEUE_DELAY = 10; // longer delay before doing anything after errors (other than TIMEOUT)
// a delay before processing the queue after requeuing 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;
// delay before processing the queue after error==TIMEOUT requests. this is a less severe error than other errors
this.TIMEOUT_REQUEST_RUN_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
// render queue
// number of items to process in each render pass. there are pros and cons to smaller and larger values
// (however, if using leaflet canvas rendering, it makes sense to push as much as possible through every time)
this.RENDER_BATCH_SIZE = L.Path.CANVAS ? 1E9 : (typeof android === 'undefined') ? 2000 : 500;
// delay before repeating the render loop. this gives a better chance for user interaction
this.RENDER_PAUSE = 0.05; //50ms
this.REFRESH_CLOSE = 300; // refresh time to use for close views z>12 when not idle and not moving
this.REFRESH_FAR = 900; // refresh time for far views z <= 12
this.FETCH_TO_REFRESH_FACTOR = 2; //refresh time is based on the time to complete a data fetch, times this value
// ensure we have some initial map status
@ -82,7 +93,7 @@ window.MapDataRequest.prototype.mapMoveStart = function() {
this.setStatus('paused');
this.clearTimeout();
this.pauseRenderQueue(true);
}
window.MapDataRequest.prototype.mapMoveEnd = function() {
@ -100,6 +111,7 @@ window.MapDataRequest.prototype.mapMoveEnd = function() {
if (remainingTime > this.MOVE_REFRESH) {
this.setStatus('done','Map moved, but no data updates needed');
this.refreshOnTimeout(remainingTime);
this.pauseRenderQueue(false);
return;
}
}
@ -136,8 +148,11 @@ window.MapDataRequest.prototype.refreshOnTimeout = function(seconds) {
console.log('starting map refresh in '+seconds+' seconds');
// 'this' won't be right inside the callback, so save it
var savedContext = this;
this.timer = setTimeout ( function() { savedContext.timer = undefined; savedContext.refresh(); }, seconds*1000);
// also, double setTimeout used to ensure the delay occurs after any browser-related rendering/updating/etc
var _this = this;
this.timer = setTimeout ( function() {
_this.timer = setTimeout ( function() { _this.timer = undefined; _this.refresh(); }, seconds*1000);
}, 0);
this.timerExpectedTimeoutTime = new Date().getTime() + seconds*1000;
}
@ -167,6 +182,7 @@ window.MapDataRequest.prototype.refresh = function() {
this.refreshStartTime = new Date().getTime();
this.debugTiles.reset();
this.resetRenderQueue();
// a 'set' to keep track of hard failures for tiles
this.tileErrorCount = {};
@ -211,11 +227,8 @@ window.MapDataRequest.prototype.refresh = function() {
window.runHooks ('mapDataRefreshStart', {bounds: bounds, mapZoom: mapZoom, dataZoom: dataZoom, minPortalLevel: tileParams.level, tileBounds: dataBounds});
this.render.startRenderPass();
this.render.clearPortalsBelowLevel(tileParams.level);
this.render.clearEntitiesOutsideBounds(dataBounds);
this.render.startRenderPass(tileParams.level, dataBounds);
this.render.updateEntityVisibility();
this.render.processGameEntities(artifact.getArtifactEntities());
@ -248,22 +261,16 @@ window.MapDataRequest.prototype.refresh = function() {
//TODO: with recent backend changes there are now multiple zoom levels of data that is identical except perhaps for some
// reduction of detail when zoomed out. to take good advantage of the cache, a check for cached data at a closer zoom
// but otherwise the same parameters (min portal level, tiles per edge) will mean less downloads when zooming out
// (however, the default code in getDataZoomForMapZoom currently reduces the need for this, as it forces the furthest
// out zoom tiles for a detail level)
if (this.cache && this.cache.isFresh(tile_id) ) {
// data is fresh in the cache - just render it
this.debugTiles.setState(tile_id, 'cache-fresh');
this.render.processTileData (this.cache.get(tile_id));
this.pushRenderQueue(tile_id,this.cache.get(tile_id),'cache-fresh');
this.cachedTileCount += 1;
} else {
// 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);
// }
// tile needed. calculate the distance from the centre of the screen, to optimise the load order
var latCenter = (latNorth+latSouth)/2;
@ -315,37 +322,19 @@ window.MapDataRequest.prototype.refresh = function() {
window.MapDataRequest.prototype.delayProcessRequestQueue = function(seconds,isFirst) {
if (this.timer === undefined) {
var savedContext = this;
this.timer = setTimeout ( function() { savedContext.timer = undefined; savedContext.processRequestQueue(isFirst); }, seconds*1000 );
var _this = this;
this.timer = setTimeout ( function() {
_this.timer = setTimeout ( function() { _this.timer = undefined; _this.processRequestQueue(isFirst); }, seconds*1000 );
}, 0);
}
}
window.MapDataRequest.prototype.processRequestQueue = function(isFirstPass) {
// if nothing left in the queue, end the render. otherwise, send network requests
// if nothing left in the queue, finish
if (Object.keys(this.queuedTiles).length == 0) {
this.render.endRenderPass();
var endTime = new Date().getTime();
var duration = (endTime - this.refreshStartTime)/1000;
console.log('finished requesting data! (took '+duration+' seconds to complete)');
window.runHooks ('mapDataRefreshEnd', {});
var longStatus = 'Tiles: ' + this.cachedTileCount + ' cached, ' +
this.successTileCount + ' loaded, ' +
(this.staleTileCount ? this.staleTileCount + ' stale, ' : '') +
(this.failedTileCount ? this.failedTileCount + ' failed, ' : '') +
'in ' + duration + ' seconds';
// refresh timer based on time to run this pass, with a minimum of REFRESH seconds
var minRefresh = map.getZoom()>12 ? this.REFRESH_CLOSE : this.REFRESH_FAR;
var refreshTimer = Math.max(minRefresh, duration*this.FETCH_TO_REFRESH_FACTOR);
this.refreshOnTimeout(refreshTimer);
this.setStatus (this.failedTileCount ? 'errors' : this.staleTileCount ? 'out of date' : 'done', longStatus);
// we leave the renderQueue code to handle ending the render pass now
return;
}
@ -436,8 +425,7 @@ window.MapDataRequest.prototype.requeueTile = function(id, error) {
var data = this.cache ? this.cache.get(id) : undefined;
if (data) {
// we have cached data - use it, even though it's stale
this.debugTiles.setState (id, 'cache-stale');
this.render.processTileData (data);
this.pushRenderQueue(id,data,'cache-stale');
this.staleTileCount += 1;
} else {
// no cached data
@ -472,7 +460,7 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
var timeoutTiles = [];
if (!success || !data || !data.result) {
console.warn("Request.handleResponse: request failed - requeuing...");
console.warn('Request.handleResponse: request failed - requeuing...'+(data && data.error?' error: '+data.error:''));
//request failed - requeue all the tiles(?)
@ -514,9 +502,8 @@ 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.queuedTiles) {
this.debugTiles.setState (id, 'ok');
this.render.processTileData (val);
this.pushRenderQueue(id,val,'ok');
delete this.queuedTiles[id];
this.successTileCount += 1;
@ -532,9 +519,12 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
window.runHooks('requestFinished', {success: true});
}
// set the queue delay based on any errors or timeouts
var nextQueueDelay = errorTiles.length > 0 ? this.BAD_REQUEST_RUN_QUEUE_DELAY :
timeoutTiles.length > 0 ? this.TIMEOUT_REQUEST_RUN_QUEUE_DELAY :
this.RUN_QUEUE_DELAY;
console.log ('getThinnedEntities status: '+tiles.length+' tiles: '+successTiles.length+' successful, '+timeoutTiles.length+' timed out, '+errorTiles.length+' failed');
console.log ('getThinnedEntities status: '+tiles.length+' tiles: '+successTiles.length+' successful, '+timeoutTiles.length+' timed out, '+errorTiles.length+' failed. delay '+nextQueueDelay+' seconds');
// requeue any 'timeout' tiles immediately
if (timeoutTiles.length > 0) {
@ -545,27 +535,127 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
}
}
// 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.REQUEUE_DELAY);
}, this.BAD_REQUEST_REQUEUE_DELAY*1000);
for (var i in errorTiles) {
var id = errorTiles[i];
delete this.requestedTiles[id];
this.requeueTile(id, true);
}
}
for (var i in successTiles) {
var id = successTiles[i];
delete this.requestedTiles[id];
}
//.. should this also be delayed a small amount?
this.delayProcessRequestQueue(this.RUN_QUEUE_DELAY);
this.delayProcessRequestQueue(nextQueueDelay);
}
window.MapDataRequest.prototype.resetRenderQueue = function() {
this.renderQueue = [];
if (this.renderQueueTimer) {
clearTimeout(this.renderQueueTimer);
this.renderQueueTimer = undefined;
}
this.renderQueuePaused = false;
}
window.MapDataRequest.prototype.pushRenderQueue = function (id, data, status) {
this.debugTiles.setState(id,'render-queue');
this.renderQueue.push({
id:id,
// the data in the render queue is modified as we go, so we need to copy the values of the arrays. just storing the reference would modify the data in the cache!
deleted: (data.deletedGameEntityGuids||[]).slice(0),
entities: (data.gameEntities||[]).slice(0),
status:status});
if (!this.renderQueuePaused) {
this.startQueueTimer(this.RENDER_PAUSE);
}
}
window.MapDataRequest.prototype.startQueueTimer = function(delay) {
if (this.renderQueueTimer === undefined) {
var _this = this;
this.renderQueueTimer = setTimeout( function() {
_this.renderQueueTimer = setTimeout ( function() { _this.renderQueueTimer = undefined; _this.processRenderQueue(); }, (delay||0)*1000 );
}, 0);
}
}
window.MapDataRequest.prototype.pauseRenderQueue = function(pause) {
this.renderQueuePaused = pause;
if (pause) {
if (this.renderQueueTimer) {
clearTimeout(this.renderQueueTimer);
this.renderQueueTimer = undefined;
}
} else {
if (this.renderQueue.length > 0) {
this.startQueueTimer(this.RENDER_PAUSE);
}
}
}
window.MapDataRequest.prototype.processRenderQueue = function() {
var drawEntityLimit = this.RENDER_BATCH_SIZE;
//TODO: we don't take account of how many of the entities are actually new/removed - they
// could already be drawn and not changed. will see how it works like this...
while (drawEntityLimit > 0 && this.renderQueue.length > 0) {
var current = this.renderQueue[0];
if (current.deleted.length > 0) {
var deleteThisPass = current.deleted.splice(0,drawEntityLimit);
drawEntityLimit -= deleteThisPass.length;
this.render.processDeletedGameEntityGuids(deleteThisPass);
}
if (drawEntityLimit > 0 && current.entities.length > 0) {
var drawThisPass = current.entities.splice(0,drawEntityLimit);
drawEntityLimit -= drawThisPass.length;
this.render.processGameEntities(drawThisPass);
}
if (current.deleted.length == 0 && current.entities.length == 0) {
this.renderQueue.splice(0,1);
this.debugTiles.setState(current.id, current.status);
}
}
if (this.renderQueue.length > 0) {
this.startQueueTimer(this.RENDER_PAUSE);
} else if (Object.keys(this.queuedTiles).length == 0) {
this.render.endRenderPass();
var endTime = new Date().getTime();
var duration = (endTime - this.refreshStartTime)/1000;
console.log('finished requesting data! (took '+duration+' seconds to complete)');
window.runHooks ('mapDataRefreshEnd', {});
var longStatus = 'Tiles: ' + this.cachedTileCount + ' cached, ' +
this.successTileCount + ' loaded, ' +
(this.staleTileCount ? this.staleTileCount + ' stale, ' : '') +
(this.failedTileCount ? this.failedTileCount + ' failed, ' : '') +
'in ' + duration + ' seconds';
// refresh timer based on time to run this pass, with a minimum of REFRESH seconds
var minRefresh = map.getZoom()>12 ? this.REFRESH_CLOSE : this.REFRESH_FAR;
var refreshTimer = Math.max(minRefresh, duration*this.FETCH_TO_REFRESH_FACTOR);
this.refreshOnTimeout(refreshTimer);
this.setStatus (this.failedTileCount ? 'errors' : this.staleTileCount ? 'out of date' : 'done', longStatus);
}
}

View File

@ -115,7 +115,15 @@ function extractMungeFromStock() {
foundMunges.quadKeys = result[1] || result[2];
// GET_PAGINATED_PLEXTS
var reg = new RegExp('GET_PAGINATED_PLEXTS, [a-z] = [a-z] \\|\\| nemesis.dashboard.BoundsParams.getBoundsParamsForWorld\\(\\), [a-z] = [a-z] \\|\\| -1, [a-z] = [a-z] \\|\\| -1, [a-z] = {'+mungeRegExpLit+'[a-z], '+mungeRegExpLit+'Math.round\\([a-z].bounds.sw.lat\\(\\) \\* 1E6\\), '+mungeRegExpLit+'Math.round\\([a-z].bounds.sw.lng\\(\\) \\* 1E6\\), '+mungeRegExpLit+'Math.round\\([a-z].bounds.ne.lat\\(\\) \\* 1E6\\), '+mungeRegExpLit+'Math.round\\([a-z].bounds.ne.lng\\(\\) \\* 1E6\\), '+mungeRegExpLit+'[a-z], '+mungeRegExpLit+'[a-z]};\n *[a-z]'+mungeRegExpProp+' = [a-z];\n *[a-z] > -1 && \\([a-z]'+mungeRegExpProp+' = true\\);', 'm');
var reg = new RegExp('[a-z] = {'+mungeRegExpLit+'[a-z], '
+mungeRegExpLit+'Math.round\\(1E6 \\* [a-z].bounds.sw.lat\\(\\)\\), '
+mungeRegExpLit+'Math.round\\(1E6 \\* [a-z].bounds.sw.lng\\(\\)\\), '
+mungeRegExpLit+'Math.round\\(1E6 \\* [a-z].bounds.ne.lat\\(\\)\\), '
+mungeRegExpLit+'Math.round\\(1E6 \\* [a-z].bounds.ne.lng\\(\\)\\), '
+mungeRegExpLit+'[a-z], '+mungeRegExpLit+'[a-z]};\n'
+' *[a-z]'+mungeRegExpProp+' = [a-z];\n'
+' *-1 < [a-z] && \\([a-z]'+mungeRegExpProp+' = !0\\);', 'm');
var result = reg.exec(nemesis.dashboard.network.PlextStore.prototype.getPlexts.toString());
foundMunges.desiredNumItems = result[1] || result[2];

View File

@ -168,8 +168,8 @@ window.getPortalMiscDetails = function(guid,d) {
links[link.isOrigin ? 'outgoing' : 'incoming']++;
});
function linkExpl(t) { return '<tt title="↳ incoming links\n↴ outgoing links\n• is the portal">'+t+'</tt>'; }
var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+'&nbsp;&nbsp;•&nbsp;&nbsp;'+links.outgoing+' ↴')];
function linkExpl(t) { return '<tt title="'+links.outgoing+' links out (8 max)\n'+links.incoming+' links in\n('+(links.outgoing+links.incoming)+' total)">'+t+'</tt>'; }
var linksText = [linkExpl('links'), linkExpl(links.outgoing+' out / '+links.incoming+' in')];
var player = d.captured && d.captured.capturingPlayerId
? '<span class="nickname">' + d.captured.capturingPlayerId + '</span>'

View File

@ -166,11 +166,6 @@ window.runOnSmartphonesAfterBoot = function() {
addHook('portalSelected', window.setAndroidPermalink);
}
// Force lower render limits for mobile
window.VIEWPORT_PAD_RATIO = 0.1;
window.MAX_DRAWN_PORTALS = 500;
window.MAX_DRAWN_LINKS = 200;
window.MAX_DRAWN_FIELDS = 100;
}
window.setAndroidPermalink = function() {

View File

@ -2,6 +2,8 @@
// gives user feedback about pending operations. Draws current status
// to website. Updates info in layer chooser.
window.renderUpdateStatusTimer_ = undefined;
window.renderUpdateStatus = function() {
var progress = 1;
@ -41,28 +43,6 @@ window.renderUpdateStatus = function() {
t += '...unknown...';
}
/*
if(mapRunsUserAction)
t += '<span class="help" title="Paused due to user interaction">paused</span';
else if(isIdle())
t += '<span style="color:#888">Idle</span>';
else if(window.requests._quickRefreshPending)
t += 'refreshing';
else if(window.activeRequests.length > 0)
t += window.activeRequests.length + ' requests';
else {
// tooltip with detailed tile counts
t += '<span class="help" title="'+window.statusTotalMapTiles+' tiles: '+window.statusCachedMapTiles+' cached, '+window.statusSuccessMapTiles+' successful, '+window.statusStaleMapTiles+' stale, '+window.statusErrorMapTiles+' failed">';
// basic error/out of date/up to date message
if (window.statusErrorMapTiles) t += '<span style="color:#f66">Errors</span>';
else if (window.statusStaleMapTiles) t += '<span style="color:#fa6">Out of date</span>';
else t += 'Up to date';
t += '</span>';
}
*/
t += '</span>';
//request status
@ -71,26 +51,27 @@ window.renderUpdateStatus = function() {
if (window.failedRequestCount > 0)
t += ' <span style="color:#f66">' + window.failedRequestCount + ' failed</span>'
// layer selector - enable/disable layers that aren't visible due to zoom level
//FIXME! move this somewhere more suitable!
var portalSelection = $('.leaflet-control-layers-overlays label');
//it's an array - 0=unclaimed, 1=lvl 1, 2=lvl 2, ..., 8=lvl 8 - 9 relevant entries
//mark all levels below (but not at) minlvl as disabled
portalSelection.slice(0, minlvl).addClass('disabled').attr('title', 'Zoom in to show those.');
//and all from minlvl to 8 as enabled
portalSelection.slice(minlvl, 8+1).removeClass('disabled').attr('title', '');
//it's possible that updating the status bar excessively causes some performance issues. so rather than doing it
//immediately, delay it to the next javascript event loop, cancelling any pending update
// will also cause any browser-related rendering to occur first, before the status actually updates
if (window.renderUpdateStatusTimer_) clearTimeout(window.renderUpdateStatusTimer_);
$('#innerstatus').html(t);
//$('#updatestatus').click(function() { startRefreshTimeout(10); });
//. <a style="cursor: pointer" onclick="startRefreshTimeout(10)" title="Refresh">⟳</a>';
window.renderUpdateStatusTimer_ = setTimeout ( function() {
window.renderUpdateStatusTimer_ = undefined;
if(progress == 1 && window.activeRequests.length > 0) {
// we don't know the exact progress, but we have requests (e.g. chat) running, so show it as indeterminate.
progress = -1;
}
$('#innerstatus').html(t);
//$('#updatestatus').click(function() { startRefreshTimeout(10); });
//. <a style="cursor: pointer" onclick="startRefreshTimeout(10)" title="Refresh">⟳</a>';
if(progress == 1 && window.activeRequests.length > 0) {
// we don't know the exact progress, but we have requests (e.g. chat) running, so show it as indeterminate.
progress = -1;
}
if (typeof android !== 'undefined' && android && android.setProgress)
android.setProgress(progress);
}, 0);
if (typeof android !== 'undefined' && android && android.setProgress)
android.setProgress(progress);
}

View File

@ -41,8 +41,8 @@ Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw
// points code that have been seen
function geodesicConvertLine(startLatLng, endLatLng, convertedPoints) {
var R = 6378137; // earth radius in meters (doesn't have to be exact)
var d2r = L.LatLng.DEG_TO_RAD;
var r2d = L.LatLng.RAD_TO_DEG;
var d2r = Math.PI/180.0;
var r2d = 180.0/Math.PI;
// maths based on http://williams.best.vwh.net/avform.htm#Int
@ -180,8 +180,8 @@ Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw
_calcPoints: function() {
var R = 6378137; //earth radius in meters (approx - taken from leaflet source code)
var d2r = L.LatLng.DEG_TO_RAD;
var r2d = L.LatLng.RAD_TO_DEG;
var d2r = Math.PI/180.0;
var r2d = 180.0/Math.PI;
//console.log("geodesicCircle: radius = "+this._mRadius+"m, centre "+this._latlng.lat+","+this._latlng.lng);
// circle radius as an angle from the centre of the earth

View File

@ -5072,10 +5072,35 @@ L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path :
return this;
},
onAdd: function (map) {
this._map = map;
if (!this._container) {
this._initElements();
this._initEvents();
}
this.projectLatlngs();
this._updatePath();
if (this._container) {
this._map._pathRoot.appendChild(this._container);
}
this.fire('add');
map.on({
'viewreset': this.projectLatlngs,
'moveend': this._updatePath,
'canvasredraw': this._updatePath
}, this);
},
onRemove: function (map) {
map
.off('viewreset', this.projectLatlngs, this)
.off('moveend', this._updatePath, this);
.off('moveend', this._updatePath, this)
.off('canvasredraw', this._updatePath, this);
if (this.options.clickable) {
this._map.off('click', this._onClick, this);
@ -5089,13 +5114,13 @@ L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path :
_requestUpdate: function () {
if (this._map && !L.Path._updateRequest) {
L.Path._updateRequest = L.Util.requestAnimFrame(this._fireMapMoveEnd, this._map);
L.Path._updateRequest = L.Util.requestAnimFrame(this._fireCanvasRedraw, this._map);
}
},
_fireMapMoveEnd: function () {
_fireCanvasRedraw: function () {
L.Path._updateRequest = null;
this.fire('moveend');
this.fire('canvasredraw');
},
_initElements: function () {
@ -5215,6 +5240,7 @@ L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {}
this.on('zoomend', this._endPathZoom);
}
this.on('moveend', this._updateCanvasViewport);
this.on('canvasredraw', this._updateCanvasViewport);
this._updateCanvasViewport();
}
},

View File

@ -28,7 +28,7 @@ window.S2 = {};
var LatLngToXYZ = function(latLng) {
var d2r = L.LatLng.DEG_TO_RAD;
var d2r = Math.PI/180.0;
var phi = latLng.lat*d2r;
var theta = latLng.lng*d2r;
@ -39,7 +39,7 @@ var LatLngToXYZ = function(latLng) {
};
var XYZToLatLng = function(xyz) {
var r2d = L.LatLng.RAD_TO_DEG;
var r2d = 180.0/Math.PI;
var lat = Math.atan2(xyz[2], Math.sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]));
var lng = Math.atan2(xyz[1], xyz[0]);

30
main.js
View File

@ -1,7 +1,7 @@
// ==UserScript==
// @id ingress-intel-total-conversion@jonatkins
// @name IITC: Ingress intel map total conversion
// @version 0.16.6.@@DATETIMEVERSION@@
// @version 0.16.7.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -23,7 +23,6 @@ window.iitcBuildDate = '@@BUILDDATE@@';
window.onload = function() {};
document.body.onload = function() {};
// rescue user data from original page
var scr = document.getElementsByTagName('script');
for(var x in scr) {
@ -115,12 +114,23 @@ function wrapper(info) {
// (not the full GM_info - it contains the ENTIRE script source!)
window.script_info = info;
// disabling of some cruft left behind by the stock site
try {
goog.events.removeAll();
goog.Timer.clear();
} catch(e) {
console.warn('Exception from trying to clear stock site stuff');
console.warn(e);
debugger; // debugger break
}
// LEAFLET PREFER CANVAS ///////////////////////////////////////////////
// Set to true if Leaflet should draw things using Canvas instead of SVG
// Disabled for now because it has several bugs: flickering, constant
// CPU usage and it continuously fires the moveend event.
L_PREFER_CANVAS = false;
//L_PREFER_CANVAS = false;
// CONFIG OPTIONS ////////////////////////////////////////////////////
window.REFRESH = 30; // refresh view every 30s (base time)
@ -129,20 +139,8 @@ window.ON_MOVE_REFRESH = 2.5; //refresh time to use after a movement event
window.MINIMUM_OVERRIDE_REFRESH = 10; //limit on refresh time since previous refresh, limiting repeated move refresh rate
window.REFRESH_GAME_SCORE = 15*60; // refresh game score every 15 minutes
window.MAX_IDLE_TIME = 4*60; // stop updating map after 4min idling
window.PRECACHE_PLAYER_NAMES_ZOOM = 17; // zoom level to start pre-resolving player names
window.HIDDEN_SCROLLBAR_ASSUMED_WIDTH = 20;
window.SIDEBAR_WIDTH = 300;
// chat messages are requested for the visible viewport. On high zoom
// levels this gets pretty pointless, so request messages in at least a
// X km radius.
window.CHAT_MIN_RANGE = 6;
// this controls how far data is being drawn outside the viewport. Set
// it 0 to only draw entities that intersect the current view. A value
// of one will render an area twice the size of the viewport (or some-
// thing like that, Leaflet doc isnt too specific). Setting it too low
// makes the missing data on move/zoom out more obvious. Setting it too
// high causes too many items to be drawn, making drag&drop sluggish.
window.VIEWPORT_PAD_RATIO = 0.3;
// how many items to request each query
window.CHAT_PUBLIC_ITEMS = 50;
@ -182,8 +180,6 @@ window.NOMINATIM = 'http://nominatim.openstreetmap.org/search?format=json&limit=
// INGRESS CONSTANTS /////////////////////////////////////////////////
// http://decodeingress.me/2012/11/18/ingress-portal-levels-and-link-range/
window.RESO_NRG = [0, 1000, 1500, 2000, 2500, 3000, 4000, 5000, 6000];
window.MAX_XM_PER_LEVEL = [0, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000];
window.MIN_AP_FOR_LEVEL = [0, 2500, 20000, 70000, 150000, 300000, 600000, 1200000];
window.HACK_RANGE = 40; // in meters, max. distance from portal to be able to access it
window.OCTANTS = ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE'];
window.OCTANTS_ARROW = ['→', '↗', '↑', '↖', '←', '↙', '↓', '↘'];

View File

@ -1,5 +1,3 @@
<component name="CopyrightManager">
<settings default="">
<module2copyright />
</settings>
<settings default="" />
</component>

View File

@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cradle.iitc_mobile"
android:installLocation="auto"
android:versionCode="67"
android:versionName="0.10.6">
android:versionCode="68"
android:versionName="0.10.7">
<uses-sdk
android:minSdkVersion="14"

View File

@ -1,9 +1,8 @@
How does this basically work?
-----------------------------
At the moment, the Android App is a WebView which renders the normal web page. The IITC script is injected by calling ```iitc_view.loadIITC_JS(Context)```. The app uses a local version of the script, which is located in the assets folder, if no external source is given (see "pref\_iitc\_source").
Communication from app to script is handled by loading Javascript function calls. For example: ```iitc_view.loadUrl("javascript: window.goBack();");```
At the moment, the Android App is a WebView which renders the normal web page. The IITC script is injected by calling ```iitc_view.loadIITC_JS(Context)```. The app uses a local version of the script, which is located in the assets folder.
Communication from app to script is handled by loading Javascript function calls. For example: ```iitc_view.loadUrl("javascript: window.alert('foo');");```
Communication from script to app is handled by the JavascriptInterface (see /mobile/src/com/cradle/iitc\_mobile/IITC_JSInterface.java). If a method ```foo(String)``` is defined in JSInterface, it can be called by ```android.foo("Hello World")``` in the IITC script.

View File

@ -1,11 +1,13 @@
ingress intel total conversion mobile (IITCM)
ingress intel total conversion mobile (IITCm)
=====================================
The Android App behaves like the desktop version, but uses the mobile view, which is optimized for mobile devices, as default. Furthermore, there are some nice additions:
- it should be much faster than the standard mobile ingress intel map
- plugin support
- supports all official IITC plugins
- easy installation of unofficial plugins (installation via plugin preference, click on *.user.js file or URL, email attachement etc.)
- show users current location
@ -13,17 +15,13 @@ The Android App behaves like the desktop version, but uses the mobile view, whic
- a geolocate button (you have to enable GPS satellites + location access to use this feature)
- possibility to use a custom IITC script source
- a click on Portal link copies it to clipboard
- in-app layer chooser
- in-app IITC buttons
- in-app search
- support for unofficial plugins. Just copy the *.user.js files to ```<storage_path>/IITC_Mobile/plugins/``` and they should appear at the top of the plugin list. Note: For every option a new persistent database entry is created. If you want to remove a plugin from your external storage you want to ensure that it is disabled in the settings, otherwise IITCM will always try to load it on start-up. If you messed this up you can wipe app data or add the plugin back to storage, disable it and remove it. Another option would be: Do nothing...it should work even so.
- configurable fullscreen modes (includes immersive mode on Android 4.4+)
- navigation drawers for IITC views, layer chooser and highlighters
- in-app screenshots
- developer mode: all script source will be loaded from ```<storage_path>/IITC_Mobile/dev/```

View File

@ -66,10 +66,13 @@ window.plugin.userLocation.setup = function() {
};
window.plugin.userLocation.onZoomEnd = function() {
if(window.map.getZoom() < 16)
window.plugin.userLocation.locationLayer.removeLayer(window.plugin.userLocation.circle);
else
window.plugin.userLocation.locationLayer.addLayer(window.plugin.userLocation.circle);
if(window.map.getZoom() < 16 || L.Path.CANVAS) {
if (window.plugin.userLocation.locationLayer.hasLayer(window.plugin.userLocation.circle))
window.plugin.userLocation.locationLayer.removeLayer(window.plugin.userLocation.circle);
} else {
if (!window.plugin.userLocation.locationLayer.hasLayer(window.plugin.userLocation.circle))
window.plugin.userLocation.locationLayer.addLayer(window.plugin.userLocation.circle);
}
};
window.plugin.userLocation.locate = function(lat, lng, accuracy) {

View File

@ -334,7 +334,7 @@ public class IITC_FileManager {
// create the chooser Intent
final Intent target = new Intent(Intent.ACTION_GET_CONTENT)
.setType("file/*")
.setType("text/*")
.addCategory(Intent.CATEGORY_OPENABLE);
final IITC_Mobile iitc = (IITC_Mobile) mActivity;

View File

@ -16,6 +16,7 @@ import java.io.ByteArrayInputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class IITC_WebViewClient extends WebViewClient {
@ -57,11 +58,9 @@ public class IITC_WebViewClient extends WebViewClient {
private void loadScripts(final IITC_WebView view) {
final List<String> scripts = new LinkedList<String>();
scripts.add("script" + DOMAIN + "/total-conversion-build.user.js");
// get the plugin preferences
final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mIitc);
final Map<String, ?> all_prefs = sharedPref.getAll();
final TreeMap<String, ?> all_prefs = new TreeMap<String, Object>(sharedPref.getAll());
// iterate through all plugins
for (final Map.Entry<String, ?> entry : all_prefs.entrySet()) {
@ -80,6 +79,8 @@ public class IITC_WebViewClient extends WebViewClient {
scripts.add("script" + DOMAIN + "/user-location.user.js");
}
scripts.add("script" + DOMAIN + "/total-conversion-build.user.js");
final String js = "(function(){['" + TextUtils.join("','", scripts) + "'].forEach(function(src) {" +
"var script = document.createElement('script');script.src = '//'+src;" +
"(document.body || document.head || document.documentElement).appendChild(script);" +

View File

@ -675,6 +675,35 @@
}
}
window.plugin.bookmarks.autoDrawCalcDistance = function() {
var latlngs = [];
var uuu = $('#bkmrksAutoDrawer a.bkmrk.selected').each(function(i) {
var tt = $(this).data('latlng');
latlngs[i] = tt;
});
var distance = null;
if(latlngs.length == 2) {
distance = L.latLng(latlngs[0]).distanceTo(latlngs[1]);
}
$('#bkmrksAutoDrawerDistance').remove();
if(distance !== null) {
distance = Math.round(distance);
var text = 'Distance between portals: ';
if(distance > 1000)
text += digits(distance / 1000) + 'km';
else
text += digits(distance) + 'm';
$('<div>')
.html(text)
.attr('id', 'bkmrksAutoDrawerDistance')
.appendTo('#bkmrksAutoDrawer');
}
}
window.plugin.bookmarks.dialogLoadList = function() {
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>';
@ -724,7 +753,9 @@
+ '<input style="vertical-align: middle;" type="checkbox" id="bkmrkClearSelection" checked>'
+ ' Clear selection after drawing</label>'
+ '<p style="color:red;text-align:center;margin-bottom:9px;">You must select 2 or 3 portals.</p>'
+ '<div onclick="window.plugin.bookmarks.autoDrawCalcDistance();return false;">'
+ element
+ '</div>'
+ '</div>';
}
return r;
@ -872,6 +903,8 @@
iconSize: [30,40]
})
});
star.on('click', function() { renderPortalDetails(guid); });
window.plugin.bookmarks.starLayers[guid] = star;
star.addTo(window.plugin.bookmarks.starLayerGroup);
}

View File

@ -0,0 +1,50 @@
// ==UserScript==
// @id iitc-plugin-canvas-render@jonatkins
// @name IITC plugin: Use Canvas rendering
// @category Tweaks
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] EXPERIMENTAL: use canvas-based rendering. Can be faster when viewing dense areas. Limited testing of the feature so far
// @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 unsafeWindow
// ==/UserScript==
// NON-STANDARD plugin - try and set the variable early, as
// we need this global variable set before leaflet initialises
window.L_PREFER_CANVAS = true;
if (typeof unsafeWindow !== 'undefined') unsafeWindow.L_PREFER_CANVAS = true; //doesn't actually work... :/
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// we need this global variable set before leaflet initialises
window.L_PREFER_CANVAS = true;
// use own namespace for plugin
window.plugin.canvasRendering = function() {};
window.plugin.canvasRendering.setup = function() {
// nothing we can do here - other than check that canvas rendering was enabled
if (!L.Path.CANVAS) {
dialog({
title:'Canvas Render Warning',
text:'The Canvas Rendering plugin failed to enable canvas rendering in leaflet. This will occur if it initialises too late.\n'
+'Try re-ordering userscripts so Canvas Rendering is before the main IITC script.'
});
}
};
var setup = window.plugin.canvasRendering.setup;
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,115 @@
// ==UserScript==
// @id iitc-plugin-marker-canvas-icon@jonatkins
// @name IITC plugin: Marker drawn using icons from canvas data URLs
// @category Tweaks
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] EXPERIMENTAL: draw markers using individual Leaflet Icons, created from canvas elements converted to data: URLs
// @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.markerIconCanvasUrl = function() {};
window.plugin.markerIconCanvasUrl.setup = function() {
// create a new marker. 'data' contain the IITC-specific entity data to be stored in the object options
window.createMarker = function(latlng, data) {
var icon = createMarkerIcon(data);
var options = L.extend({}, data, { icon: icon });
var marker = L.marker (latlng, options);
marker.bringToFront = function(){}; //TEMP - until the rest of IITC code is changed to take account of non-path markers
return marker;
}
window.setMarkerStyle = function(marker, selected) {
var icon = createMarkerIcon(marker.options,selected);
marker.setIcon(icon);
}
window.createMarkerIcon = function(details,selected) {
var scale = window.portalMarkerScale();
var lvlWeight = Math.max(2, Math.floor(details.level) / 1.5) * scale;
var lvlRadius = (details.team === window.TEAM_NONE ? 7 : Math.floor(details.level) + 4) * scale;
lvlRadius += (L.Browser.mobile ? PORTAL_RADIUS_ENLARGE_MOBILE*scale : 0);
var fillColor = COLORS[details.team];
var fillAlpha = 0.5;
var lineColor = selected ? COLOR_SELECTED_PORTAL : COLORS[details.team];
var lineAlpha = 1.0;
var cacheKey = ([lvlRadius,lvlWeight,fillColor,fillAlpha,lineColor,lineAlpha]).join(':');
if (!window.markerIconCache[cacheKey]) {
window.markerIconCache[cacheKey] = createNewMarkerIcon(lvlRadius,lvlWeight,fillColor,fillAlpha,lineColor,lineAlpha);
}
return window.markerIconCache[cacheKey];
}
window.markerIconCache = {};
window.createNewMarkerIcon = function (radius,weight,fillcol,fillalpha,linecol,linealpha) {
var size = Math.ceil(radius + weight/2)*2;
var anchor = Math.floor(size/2);
var canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(anchor,anchor,radius,0,2*Math.PI);
ctx.fillStyle = fillcol;
ctx.globalAlpha = fillalpha;
ctx.fill();
ctx.lineWidth = weight;
ctx.strokeStyle = linecol;
ctx.globalAlpha = linealpha;
ctx.stroke();
var dataurl = canvas.toDataURL();
return L.icon({
iconUrl: dataurl,
iconSize: [size,size],
iconAnchor: [anchor,anchor]
});
}
};
var setup = window.plugin.markerIconCanvasUrl.setup;
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,79 @@
// ==UserScript==
// @id iitc-plugin-marker-divicon-svg@jonatkins
// @name IITC plugin: Marker drawn using separate SVGs
// @category Tweaks
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] EXPERIMENTAL: draw markers using individual Leaflet DivIcons, as SVG
// @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.markerDivIconSvg = function() {};
window.plugin.markerDivIconSvg.setup = function() {
// create a new marker. 'data' contain the IITC-specific entity data to be stored in the object options
window.createMarker = function(latlng, data) {
var icon = createMarkerDivIcon(data);
var options = L.extend({}, data, { icon: icon });
var marker = L.marker (latlng, options);
return marker;
}
window.setMarkerStyle = function(marker, selected) {
var icon = createMarkerDivIcon(marker.options);
marker.setIcon(icon);
}
window.createMarkerDivIcon = function(details) {
var scale = window.portalMarkerScale();
var lvlWeight = Math.max(2, Math.floor(details.level) / 1.5) * scale;
var lvlRadius = (details.team === window.TEAM_NONE ? 7 : Math.floor(details.level) + 4) * scale;
lvlRadius += (L.Browser.mobile ? PORTAL_RADIUS_ENLARGE_MOBILE*scale : 0);
var size = Math.ceil(lvlRadius + lvlWeight/2)*2;
var anchor = Math.floor(size/2);
var svg = '<svg width="'+size+'" height="'+size+'">'
+ '<circle cx="'+anchor+'" cy="'+anchor+'" r="'+lvlRadius+'" stroke="'+COLORS[details.team]+'" stroke-width="'+lvlWeight+'" fill="'+COLORS[details.team]+'" fill-opacity="0.5" />'
+ '</svg>';
return L.divIcon({
iconSize: [size,size],
iconAnchor: [anchor,anchor],
className: 'portal-marker',
html: svg
});
}
};
var setup = window.plugin.markerDivIconSvg.setup;
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -2,7 +2,7 @@
// @id iitc-plugin-guess-player-levels@breunigs
// @name IITC plugin: guess player level
// @category Info
// @version 0.5.1.@@DATETIMEVERSION@@
// @version 0.5.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -84,6 +84,7 @@ window.plugin.guessPlayerLevels.setLevelTitle = function(dom) {
var el = $(dom);
var nick = el.text();
if (nick[0] == '@') nick = nick.substring(1);
var details = window.plugin.guessPlayerLevels.fetchLevelDetailsByPlayer(nick);

View File

@ -2,7 +2,7 @@
// @id max-links@boombuler
// @name IITC plugin: Max Links
// @category Layer
// @version 0.4.2.@@DATETIMEVERSION@@
// @version 0.4.3.@@DATETIMEVERSION@@
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Calculate how to link the portals to create a reasonably tidy set of links/fields. Enable from the layer chooser. (Max Links is a poor name, but remains for historical reasons.)
@ -68,11 +68,6 @@ window.plugin.maxLinks.updateLayer = function() {
window.plugin.maxLinks.layer.clearLayers();
if (Object.keys(window.portals).length > window.plugin.maxLinks.MAX_PORTALS_TO_LINK) {
window.plugin.maxLinks.addErrorMarker();
return;
}
var locations = [];
var bounds = map.getBounds();
@ -81,9 +76,15 @@ window.plugin.maxLinks.updateLayer = function() {
if (bounds.contains(ll)) {
var p = map.project (portal.getLatLng(), window.plugin.maxLinks.PROJECT_ZOOM);
locations.push(p);
if (locations.length > window.plugin.maxLinks.MAX_PORTALS_TO_LINK) return false; //$.each break
}
});
if (locations.length > window.plugin.maxLinks.MAX_PORTALS_TO_LINK) {
window.plugin.maxLinks.addErrorMarker();
return;
}
var triangles = window.delaunay.triangulate(locations);
var drawnLinkCount = 0;

View File

@ -399,7 +399,9 @@ window.plugin.playerTracker.drawData = function() {
dashArray: "5,8"
};
L.multiPolyline(polyLine, opts).addTo(plugin.playerTracker.drawnTracesEnl);
$.each(polyLine,function(ind,poly) {
L.polyline(poly, opts).addTo(plugin.playerTracker.drawnTracesEnl);
});
});
$.each(polyLineByAgeRes, function(i, polyLine) {
if(polyLine.length === 0) return true;
@ -412,7 +414,9 @@ window.plugin.playerTracker.drawData = function() {
dashArray: "5,8"
};
L.multiPolyline(polyLine, opts).addTo(plugin.playerTracker.drawnTracesRes);
$.each(polyLine, function(ind,poly) {
L.polyline(poly, opts).addTo(plugin.playerTracker.drawnTracesRes);
});
});
}

View File

@ -2,7 +2,7 @@
// @id iitc-plugin-portal-level-numbers@rongou
// @name IITC plugin: Portal Level Numbers
// @category Layer
// @version 0.1.2.@@DATETIMEVERSION@@
// @version 0.1.4.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -19,50 +19,16 @@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalLevelNumbers = function() {};
window.plugin.portalLevelNumbers = function() {
};
window.plugin.portalLevelNumbers.ICON_SIZE = 12;
window.plugin.portalLevelNumbers.MOBILE_SCALE = 1.5;
window.plugin.portalLevelNumbers.levelLayers = {};
window.plugin.portalLevelNumbers.levelLayerGroup = null;
// Use portal add and remove event to control render of portal level numbers
window.plugin.portalLevelNumbers.portalAdded = function(data) {
data.portal.on('add', function() {
plugin.portalLevelNumbers.renderLevel(this.options.guid, this.getLatLng());
});
data.portal.on('remove', function() {
plugin.portalLevelNumbers.removeLevel(this.options.guid);
});
}
window.plugin.portalLevelNumbers.renderLevel = function(guid,latLng) {
plugin.portalLevelNumbers.removeLevel(guid);
var p = window.portals[guid];
var levelNumber = p.options.level;
var level = L.marker(latLng, {
icon: L.divIcon({
className: 'plugin-portal-level-numbers',
iconAnchor: [6,7],
iconSize: [12,10],
html: levelNumber
}),
guid: guid
});
plugin.portalLevelNumbers.levelLayers[guid] = level;
level.addTo(plugin.portalLevelNumbers.levelLayerGroup);
}
window.plugin.portalLevelNumbers.removeLevel = function(guid) {
var previousLayer = plugin.portalLevelNumbers.levelLayers[guid];
if(previousLayer) {
plugin.portalLevelNumbers.levelLayerGroup.removeLayer(previousLayer);
delete plugin.portalLevelNumbers.levelLayers[guid];
}
}
var setup = function() {
window.plugin.portalLevelNumbers.setupCSS = function() {
$("<style>")
.prop("type", "text/css")
.html(".plugin-portal-level-numbers {\
@ -75,12 +41,140 @@ var setup = function() {
-webkit-text-size-adjust:none;\
}")
.appendTo("head");
}
window.plugin.portalLevelNumbers.removeLabel = function(guid) {
var previousLayer = window.plugin.portalLevelNumbers.levelLayers[guid];
if(previousLayer) {
window.plugin.portalLevelNumbers.levelLayerGroup.removeLayer(previousLayer);
delete plugin.portalLevelNumbers.levelLayers[guid];
}
}
window.plugin.portalLevelNumbers.addLabel = function(guid,latLng) {
// remove old layer before updating
window.plugin.portalLevelNumbers.removeLabel(guid);
// add portal level to layers
var p = window.portals[guid];
var levelNumber = p.options.level;
var level = L.marker(latLng, {
icon: L.divIcon({
className: 'plugin-portal-level-numbers',
iconSize: [window.plugin.portalLevelNumbers.ICON_SIZE, window.plugin.portalLevelNumbers.ICON_SIZE],
html: levelNumber
}),
guid: guid
});
plugin.portalLevelNumbers.levelLayers[guid] = level;
level.addTo(plugin.portalLevelNumbers.levelLayerGroup);
}
window.plugin.portalLevelNumbers.updatePortalLabels = function() {
var SQUARE_SIZE = L.Browser.mobile ? (window.plugin.portalLevelNumbers.ICON_SIZE + 3) * window.plugin.portalLevelNumbers.MOBILE_SCALE
: (window.plugin.portalLevelNumbers.ICON_SIZE + 3);
// as this is called every time layers are toggled, there's no point in doing it when the layer is off
if (!map.hasLayer(window.plugin.portalLevelNumbers.levelLayerGroup)) {
return;
}
var portalPoints = {};
for (var guid in window.portals) {
var p = window.portals[guid];
if (p._map) { // only consider portals added to the map
var point = map.project(p.getLatLng());
portalPoints[guid] = point;
}
}
// for efficient testing of intersection, group portals into buckets based on the defined rectangle size
var buckets = {};
for (var guid in portalPoints) {
var point = portalPoints[guid];
var bucketId = L.point([Math.floor(point.x/(SQUARE_SIZE*2)),Math.floor(point.y/SQUARE_SIZE*2)]);
// 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 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 rectangle. this is so that there's no left/right
// overlap between two different portals text
var southWest = point.subtract([SQUARE_SIZE, SQUARE_SIZE]);
var northEast = point.add([SQUARE_SIZE, SQUARE_SIZE]);
var largeBounds = L.bounds(southWest, northEast);
for (var otherGuid in bucketGuids) {
// do not check portals already marked as covered
if (guid != otherGuid && !coveredPortals[otherGuid]) {
var otherPoint = portalPoints[otherGuid];
if (largeBounds.contains(otherPoint)) {
// another portal is within the rectangle - remove if it has not a higher level
if (portals[guid].options.level > portals[otherGuid].options.level) continue;
else coveredPortals[guid] = true;
break;
}
}
}
}
}
for (var guid in coveredPortals) {
delete portalPoints[guid];
}
// remove any not wanted
for (var guid in window.plugin.portalLevelNumbers.levelLayers) {
if (!(guid in portalPoints)) {
window.plugin.portalLevelNumbers.removeLabel(guid);
}
}
// and add those we do
for (var guid in portalPoints) {
window.plugin.portalLevelNumbers.addLabel(guid, portals[guid].getLatLng());
}
}
// as calculating portal marker visibility can take some time when there's lots of portals shown, we'll do it on
// a short timer. this way it doesn't get repeated so much
window.plugin.portalLevelNumbers.delayedUpdatePortalLabels = function(wait) {
if (window.plugin.portalLevelNumbers.timer === undefined) {
window.plugin.portalLevelNumbers.timer = setTimeout ( function() {
window.plugin.portalLevelNumbers.timer = undefined;
window.plugin.portalLevelNumbers.updatePortalLabels();
}, wait*1000);
}
}
var setup = function() {
window.plugin.portalLevelNumbers.setupCSS();
window.plugin.portalLevelNumbers.levelLayerGroup = new L.LayerGroup();
window.addLayerGroup('Portal Levels', window.plugin.portalLevelNumbers.levelLayerGroup, true);
window.addHook('portalAdded', window.plugin.portalLevelNumbers.portalAdded);
window.addHook('requestFinished', function() { setTimeout(function(){window.plugin.portalLevelNumbers.delayedUpdatePortalLabels(3.0);},1); });
window.addHook('mapDataRefreshEnd', function() { window.plugin.portalLevelNumbers.delayedUpdatePortalLabels(0.5); });
window.map.on('overlayadd overlayremove', function() { setTimeout(function(){window.plugin.portalLevelNumbers.delayedUpdatePortalLabels(1.0);},1); });
}
// PLUGIN END //////////////////////////////////////////////////////////

View File

@ -2,7 +2,7 @@
// @id iitc-plugin-portals-list@teo96
// @name IITC plugin: show list of portals
// @category Info
// @version 0.1.0.@@DATETIMEVERSION@@
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -84,8 +84,8 @@ window.plugin.portalslist.getPortals = function() {
'guid': i,
'teamN': teamN, // TEAM_NONE, TEAM_RES or TEAM_ENL
'team': d.team, // "NEUTRAL", "RESISTANCE" or "ENLIGHTENED"
'name': d.title,
'nameLower': d.title.toLowerCase(),
'name': d.title || '(untitled)',
'nameLower': d.title && d.title.toLowerCase(),
'level': portal.options.level,
'health': d.health,
'resCount': d.resCount,
@ -242,7 +242,7 @@ window.plugin.portalslist.getPortalLink = function(portal,guid) {
var latlng = [coord.lat, coord.lng].join();
var jsSingleClick = 'window.renderPortalDetails(\''+guid+'\');return false';
var jsDoubleClick = 'window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false';
var perma = '/intel?latE6='+coord.lat+'&lngE6='+coord.lng+'&z=17&pguid='+guid;
var perma = '/intel?ll='+coord.lat+','+coord.lng+'&z=17&pll='+coord.lat+','+coord.lng;
//Use Jquery to create the link, which escape characters in TITLE and ADDRESS of portal
var a = $('<a>',{

View File

@ -149,7 +149,7 @@ window.plugin.regions.update = function() {
// the six cube side boundaries. we cheat by hard-coding the coords as it's simple enough
var latLngs = [ [45,-180], [35.264389682754654,-135], [35.264389682754654,-45], [35.264389682754654,45], [35.264389682754654,135], [45,180]];
var globalCellOptions = {color: 'red', weight: 7, opacity: 0.5};
var globalCellOptions = {color: 'red', weight: 7, opacity: 0.5, clickable: false };
for (var i=0; i<latLngs.length-1; i++) {
// the geodesic line code can't handle a line/polyline spanning more than (or close to?) 180 degrees, so we draw
@ -191,7 +191,7 @@ window.plugin.regions.drawCell = function(cell) {
// the level 6 cells have noticible errors with non-geodesic lines - and the larger level 4 cells are worse
// NOTE: we only draw two of the edges. as we draw all cells on screen, the other two edges will either be drawn
// from the other cell, or be off screen so we don't care
var region = L.geodesicPolyline([corners[0],corners[1],corners[2]], {fill: false, color: color, opacity: 0.5, weight: 5, clickable: false});
var region = L.geodesicPolyline([corners[0],corners[1],corners[2]], {fill: false, color: color, opacity: 0.5, weight: 5, clickable: false });
window.plugin.regions.regionLayer.addLayer(region);

View File

@ -13,6 +13,29 @@ offers many more features. It is available for
<h3>Latest news</h3>
<h4>14th March 2014</h4>
<p>
IITC 0.16.6 and IITC Mobile 0.10.6 have just been released. This is a critical update required to successfully load
portals when zoomed in (L3+ or closer) to the map. Changes include:
</p>
<ul>
<li>debug tiles fade for completed tiles</li>
<li>warning in sidebar when standard layers are turned off</li>
<li>player level: fixed AP values for L2/L3</li>
<li>Plugins:
<ul>
<li>portal-counts: percentage in pie chart</li>
<li>guess-player-levels: guess level based on portal attacks (attack range as calculated from log)</li>
</ul></li>
<li>Mobile:
<ul>
<li>send screenshot from menu</li>
<li>fixed sharing interface (caused crash on some devices)</li>
<li>show loading indicator while log is being loaded</li>
<li>configurable menu</li>
</ul></li>
</ul>
<h4>22nd February 2014</h4>
<p>
IITC 0.16.5 and IITC Mobile 0.10.5 have just been released. This version is required to work with a change made to the

View File

@ -1,5 +1,28 @@
<h2>News</h2>
<h4>14th March 2014</h4>
<p>
IITC 0.16.6 and IITC Mobile 0.10.6 have just been released. This is a critical update required to successfully load
portals when zoomed in (L3+ or closer) to the map. Changes include:
</p>
<ul>
<li>debug tiles fade for completed tiles</li>
<li>warning in sidebar when standard layers are turned off</li>
<li>player level: fixed AP values for L2/L3</li>
<li>Plugins:
<ul>
<li>portal-counts: percentage in pie chart</li>
<li>guess-player-levels: guess level based on portal attacks (attack range as calculated from log)</li>
</ul></li>
<li>Mobile:
<ul>
<li>send screenshot from menu</li>
<li>fixed sharing interface (caused crash on some devices)</li>
<li>show loading indicator while log is being loaded</li>
<li>configurable menu</li>
</ul></li>
</ul>
<h4>22nd February 2014</h4>
<p>
IITC 0.16.5 and IITC Mobile 0.10.5 have just been released. This version is required to work with a change made to the

View File

@ -15,6 +15,7 @@ builds.
<?php
include_once ( "code/desktop-download.php" );
include_once ( "code/mobile-download.php" );
$path = "test";
@ -42,25 +43,11 @@ else
{
}
$apkfile = "$path/IITC_Mobile-$path.apk";
?>
<h3 id="test-desktop">Desktop test build</h3>
<?php
iitcDesktopDownload ( $path );
?>
<hr>
<h4>Desktop test plugins</h4>
<?php
iitcDesktopPluginDownloadTable ( $path );
?>
<hr>
<h3 id="test-mobile">Mobile test build</h3>
<div class="alert alert-block alert-info">
@ -70,10 +57,6 @@ Test builds will be called "IITCm Test" - while the regular release builds remai
<?php
include_once ( "code/mobile-download.php" );
$apkfile = "$path/IITC_Mobile-$path.apk";
if ( file_exists($apkfile) )
{
@ -87,5 +70,21 @@ else
?>
<h3 id="test-desktop">Desktop test build</h3>
<?php
iitcDesktopDownload ( $path );
?>
<hr>
<h4>Desktop test plugins</h4>
<?php
iitcDesktopPluginDownloadTable ( $path );
?>
<hr>