diff --git a/build.py b/build.py index f2bf7bf5..f3ae396a 100755 --- a/build.py +++ b/build.py @@ -61,6 +61,33 @@ distUrlBase = settings.get('distUrlBase') buildMobile = settings.get('buildMobile') +# 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() { +// ensure plugin framework is there, even if iitc is not yet loaded +if(typeof window.plugin !== 'function') window.plugin = function() {}; + +""" +pluginWrapperEnd = """ +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} +} // wrapper end +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script); + +""" + + def readfile(fn): with io.open(fn, 'Ur', encoding='utf8') as f: return f.read() @@ -137,6 +164,9 @@ 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) + return script @@ -203,7 +233,7 @@ if buildMobile: # compile the user location script fn = "user-location.user.js" - script = readfile("mobile/" + fn) + 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) @@ -221,11 +251,14 @@ if buildMobile: shutil.copy(os.path.join(outDir,"user-location.user.js"), "mobile/assets/user-location.user.js") # also copy plugins try: - os.makedirs("mobile/assets/plugins") + shutil.rmtree("mobile/assets/plugins") except: pass - shutil.rmtree("mobile/assets/plugins") - shutil.copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins", ignore=shutil.ignore_patterns('*.meta.js', 'force-https*', 'privacy-view*', 'speech-search*', 'basemap-cloudmade*')) + shutil.copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins", + # do not include desktop-only plugins to mobile assets + ignore=shutil.ignore_patterns('*.meta.js', + 'force-https*', 'privacy-view*', 'speech-search*', + 'basemap-cloudmade*', 'scroll-wheel-zoom-disable*')) if buildMobile != 'copyonly': diff --git a/code/boot.js b/code/boot.js index 1277c6d8..4b257942 100644 --- a/code/boot.js +++ b/code/boot.js @@ -10,15 +10,23 @@ window.showLayerChooser = true; window.setupLargeImagePreview = function() { $('#portaldetails').on('click', '.imgpreview', function() { var img = $(this).find('img')[0]; + var details = $(this).find('div.portalDetails')[0]; //dialogs have 12px padding around the content - var dlgWidth = Math.max(img.naturalWidth+24,400); - dialog({ - html: '
' + img.outerHTML + '
', - title: $(this).parent().find('h3.title').text(), - width: dlgWidth, - }); - - }); + var dlgWidth = Math.max(img.naturalWidth+24,500); + if (details) { + dialog({ + html: '
' + img.outerHTML + '
' + details.outerHTML, + title: $(this).parent().find('h3.title').text(), + width: dlgWidth, + }); + } else { + dialog({ + html: '
' + img.outerHTML + '
', + title: $(this).parent().find('h3.title').text(), + width: dlgWidth, + }); + } + }); } // adds listeners to the layer chooser such that a long press hides @@ -100,12 +108,6 @@ window.setupMap = function() { //OpenStreetMap attribution - required by several of the layers osmAttribution = 'Map data © OpenStreetMap contributors'; - - //CloudMade layers - only 500,000 tiles/month in their free plan. nowhere near enough for IITC - //var cmOpt = {attribution: osmAttribution+', Imagery © CloudMade', maxZoom: 18, detectRetina: true}; - //var cmMin = new L.TileLayer('http://{s}.tile.cloudmade.com/{your api key here}/22677/256/{z}/{x}/{y}.png', cmOpt); - //var cmMid = new L.TileLayer('http://{s}.tile.cloudmade.com/{your api key here}/999/256/{z}/{x}/{y}.png', cmOpt); - //MapQuest offer tiles - http://developer.mapquest.com/web/products/open/map //their usage policy has no limits (except required notification above 4000 tiles/sec - we're perhaps at 50 tiles/sec based on CloudMade stats) var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ]; @@ -130,6 +132,13 @@ window.setupMap = function() { {zoomControl: window.showZoom} )); + // add empty div to leaflet control areas - to force other leaflet controls to move around IITC UI elements + // TODO? move the actual IITC DOM into the leaflet control areas, so dummy
s aren't needed + if(!isSmartphone()) { + // chat window area + $(window.map._controlCorners['bottomleft']).append($('
').width(708).height(108).addClass('leaflet-control').css('margin','0')); + } + var addLayers = {}; var hiddenLayer = []; @@ -197,7 +206,7 @@ window.setupMap = function() { map.on('movestart zoomstart', function() { window.mapRunsUserAction = true; window.requests.abort(); window.startRefreshTimeout(-1); }); map.on('moveend zoomend', function() { window.mapRunsUserAction = false; window.startRefreshTimeout(ON_MOVE_REFRESH*1000); }); - window.addResumeFunction(window.requestData); + window.addResumeFunction(function() { window.startRefreshTimeout(ON_MOVE_REFRESH*1000); }); window.requests.addRefreshFunction(window.requestData); // start the refresh process with a small timeout, so the first data request happens quickly diff --git a/code/chat.js b/code/chat.js index 2f029556..8ca9377d 100644 --- a/code/chat.js +++ b/code/chat.js @@ -41,16 +41,22 @@ 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 ne = b.getNorthEast(); - var sw = b.getSouthWest(); - // round bounds in order to ignore rounding errors - var bbs = $.map([ne.lat, ne.lng, sw.lat, sw.lng], function(x) { return Math.round(x*1E4) }).join(); - if(chat._oldBBox && chat._oldBBox !== bbs) { + // set a current bounding box if none set so far + if (!chat._oldBBox) chat._oldBBox = b; + + // to avoid unnecessary chat refreshes, a small difference compared to the previous bounding box + // is not considered different + var CHAT_BOUNDINGBOX_SAME_FACTOR = 0.1; + // if the old and new box contain each other, after expanding by the factor, don't reset chat + if (!(b.pad(CHAT_BOUNDINGBOX_SAME_FACTOR).contains(chat._oldBBox) && chat._oldBBox.pad(CHAT_BOUNDINGBOX_SAME_FACTOR).contains(b))) { + console.log('Bounding Box changed, chat will be cleared (old: '+chat._oldBBox.toBBoxString()+'; new: '+b.toBBoxString()+')'); + $('#chat > div').data('needsClearing', true); - console.log('Bounding Box changed, chat will be cleared (old: '+chat._oldBBox+' ; new: '+bbs+' )'); + // need to reset these flags now because clearing will only occur // after the request is finished – i.e. there would be one almost // useless request. @@ -61,8 +67,9 @@ window.chat.genPostData = function(isFaction, storageHash, getOlderMsgs) { chat._public.data = {}; chat._public.oldestTimestamp = -1; chat._public.newestTimestamp = -1; + + chat._oldBBox = b; } - chat._oldBBox = bbs; var ne = b.getNorthEast(); var sw = b.getSouthWest(); @@ -119,7 +126,7 @@ window.chat.requestFaction = function(getOlderMsgs, isRetry) { var r = window.postAjax( 'getPaginatedPlextsV2', d, - chat.handleFaction, + function(data, textStatus, jqXHR) { chat.handleFaction(data, getOlderMsgs); }, isRetry ? function() { window.chat._requestFactionRunning = false; } : function() { window.chat.requestFaction(getOlderMsgs, true) } @@ -130,7 +137,7 @@ window.chat.requestFaction = function(getOlderMsgs, isRetry) { window.chat._faction = {data:{}, oldestTimestamp:-1, newestTimestamp:-1}; -window.chat.handleFaction = function(data, textStatus, jqXHR) { +window.chat.handleFaction = function(data, olderMsgs) { chat._requestFactionRunning = false; if(!data || !data.result) { @@ -141,7 +148,7 @@ window.chat.handleFaction = function(data, textStatus, jqXHR) { if(data.result.length === 0) return; var old = chat._faction.oldestTimestamp; - chat.writeDataToHash(data, chat._faction, false); + chat.writeDataToHash(data, chat._faction, false, olderMsgs); var oldMsgsWereAdded = old !== chat._faction.oldestTimestamp; runHooks('factionChatDataAvailable', {raw: data, processed: chat._faction.data}); @@ -170,7 +177,7 @@ window.chat.requestPublic = function(getOlderMsgs, isRetry) { var r = window.postAjax( 'getPaginatedPlextsV2', d, - chat.handlePublic, + function(data, textStatus, jqXHR) { chat.handlePublic(data, getOlderMsgs); }, isRetry ? function() { window.chat._requestPublicRunning = false; } : function() { window.chat.requestPublic(getOlderMsgs, true) } @@ -180,7 +187,7 @@ window.chat.requestPublic = function(getOlderMsgs, isRetry) { } window.chat._public = {data:{}, oldestTimestamp:-1, newestTimestamp:-1}; -window.chat.handlePublic = function(data, textStatus, jqXHR) { +window.chat.handlePublic = function(data, olderMsgs) { chat._requestPublicRunning = false; if(!data || !data.result) { @@ -191,7 +198,7 @@ window.chat.handlePublic = function(data, textStatus, jqXHR) { if(data.result.length === 0) return; var old = chat._public.oldestTimestamp; - chat.writeDataToHash(data, chat._public, true); + chat.writeDataToHash(data, chat._public, true, olderMsgs); var oldMsgsWereAdded = old !== chat._public.oldestTimestamp; runHooks('publicChatDataAvailable', {raw: data, processed: chat._public.data}); @@ -249,7 +256,7 @@ window.chat.nicknameClicked = function(event, nickname) { } } -window.chat.writeDataToHash = function(newData, storageHash, isPublicChannel) { +window.chat.writeDataToHash = function(newData, storageHash, isPublicChannel, isOlderMsgs) { $.each(newData.result, function(ind, json) { // avoid duplicates if(json[0] in storageHash.data) return true; @@ -344,7 +351,10 @@ window.chat.writeDataToHash = function(newData, storageHash, isPublicChannel) { // format: timestamp, autogenerated, HTML message, player guid storageHash.data[json[0]] = [json[1], auto, chat.renderMsg(msg, nick, time, team, msgToPlayer, systemNarrowcast), pguid]; - window.setPlayerName(pguid, nick); // free nick name resolves + // if we're processing older messages, we could be looking at pre-name change mentions or similar + // so in that case, flag it so we don't overwrite existing name cache entries. + // (it's not perfect - the initial request has the wrong value here) + window.setPlayerName(pguid, nick, isOlderMsgs); // free nick name resolves. }); } @@ -598,8 +608,6 @@ window.chat.setup = function() { if(scrollBottom(t) === 0) chat.requestPublic(false); }); - chat.request(); - window.addResumeFunction(chat.request); window.requests.addRefreshFunction(chat.request); var cls = PLAYER.team === 'ALIENS' ? 'enl' : 'res'; diff --git a/code/dialog.js b/code/dialog.js index 81c196d5..15664a9e 100644 --- a/code/dialog.js +++ b/code/dialog.js @@ -19,6 +19,11 @@ window.DIALOG_COUNT = 0; */ window.DIALOG_FOCUS = null; +/* Controls how quickly the slide toggle animation + * should play for dialog collapsing and expanding. + */ +window.DIALOG_SLIDE_DURATION = 100; + /* Creates a dialog and puts it onscreen. Takes one argument: options, a JS object. * == Common options * (text|html): The text or HTML to display in the dialog. Text is auto-converted to HTML. @@ -48,6 +53,7 @@ window.dialog = function(options) { options = options || {}; if(isSmartphone()) { options.modal = true; + options.width = 'auto'; } // Build an identifier for this dialog @@ -55,6 +61,11 @@ window.dialog = function(options) { var jqID = '#' + id; var html = ''; + // hint for iitc mobile that a dialog was opened + if (typeof android !== 'undefined' && android && android.dialogOpened) { + android.dialogOpened(id, true); + } + // Convert text to HTML if necessary if(options.text) { html = window.convertTextToTableMagic(options.text); @@ -127,12 +138,14 @@ window.dialog = function(options) { var dialog = $(this).closest('.ui-dialog'); var selector = dialog.find('.ui-dialog-content,.ui-dialog-buttonpane'); var button = dialog.find('.ui-dialog-titlebar-button-collapse'); + + // Slide toggle + $(selector).slideToggle({duration: window.DIALOG_SLIDE_DURATION}); + if(collapsed) { - $(selector).removeClass('ui-dialog-content-hidden'); $(button).removeClass('ui-dialog-titlebar-button-collapse-collapsed'); $(button).addClass('ui-dialog-titlebar-button-collapse-expanded'); } else { - $(selector).addClass('ui-dialog-content-hidden'); $(button).removeClass('ui-dialog-titlebar-button-collapse-expanded'); $(button).addClass('ui-dialog-titlebar-button-collapse-collapsed'); } @@ -167,6 +180,10 @@ window.dialog = function(options) { window.DIALOG_COUNT--; console.log('window.dialog: ' + $(this).data('id') + ' (' + $(this).dialog('option', 'title') + ') closed. ' + window.DIALOG_COUNT + ' remain.'); + // hint for iitc mobile that a dialog was closed + if (typeof android !== 'undefined' && android && android.dialogOpened) { + android.dialogOpened(id, false); + } // remove from DOM and destroy $(this).dialog('destroy').remove(); @@ -189,6 +206,10 @@ window.dialog = function(options) { // This dialog is now in focus window.DIALOG_FOCUS = this; + // hint for iitc mobile that a dialog was focused + if (typeof android !== 'undefined' && android && android.dialogFocused) { + android.dialogFocused($(window.DIALOG_FOCUS).data('id')); + } $(this).closest('.ui-dialog').find('.ui-dialog-title').removeClass('ui-dialog-title-inactive').addClass('ui-dialog-title-active'); } }, options)); diff --git a/code/idle.js b/code/idle.js index 39a4ab83..bc21a378 100644 --- a/code/idle.js +++ b/code/idle.js @@ -1,8 +1,22 @@ // IDLE HANDLING ///////////////////////////////////////////////////// -window.idleTime = 0; // in minutes +window.idleTime = 0; // in seconds +window._idleTimeLimit = MAX_IDLE_TIME; + +var IDLE_POLL_TIME = 10; + +var idlePoll = function() { + window.idleTime += IDLE_POLL_TIME; + + var hidden = (document.hidden || document.webkitHidden || document.mozHidden || document.msHidden || false); + if (hidden) { + // window hidden - use the refresh time as the idle limit, rather than the max time + window._idleTimeLimit = window.REFRESH; + } +} + +setInterval(idlePoll, IDLE_POLL_TIME*1000); -setInterval('window.idleTime += 1', 60*1000); var idleReset = function () { // update immediately when the user comes back if(isIdle()) { @@ -12,11 +26,29 @@ var idleReset = function () { }); } window.idleTime = 0; + window._idleTimeLimit = MAX_IDLE_TIME; }; -$('body').mousemove(idleReset).keypress(idleReset); + +// only reset idle on mouse move where the coordinates are actually different. +// some browsers send the event when not moving! +var _lastMouseX=-1, _lastMouseY=-1; +var idleMouseMove = function(e) { + var dX = _lastMouseX-e.clientX; + var dY = _lastMouseY-e.clientY; + var deltaSquared = dX*dX + dY*dY; + // only treat movements over 3 pixels as enough to reset us + if (deltaSquared > 3*3) { + _lastMouseX = e.clientX; + _lastMouseY = e.clientY; + idleReset(); + } +} + +$('body').keypress(idleReset); +$('body').mousemove(idleMouseMove); window.isIdle = function() { - return window.idleTime >= MAX_IDLE_TIME; + return window.idleTime >= window._idleTimeLimit; } window._onResumeFunctions = []; diff --git a/code/map_data.js b/code/map_data.js index 4c26642f..89696b27 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -1,9 +1,100 @@ - // MAP DATA ////////////////////////////////////////////////////////// // these functions handle how and which entities are displayed on the // map. They also keep them up to date, unless interrupted by user // action. +// debug - display a set of rectangles on the map representing each data tile. the colour will represent it's state +window._debugDataTileStateLayer = undefined; + +window.debugDataTileReset = function() { + if (!window._debugDataTileStateLayer) { + window._debugDataTileStateLayer = L.layerGroup(); + window.addLayerGroup("DEBUG Data Tiles", window._debugDataTileStateLayer, false); + } + + window._debugDataTileIdToRectangle = {}; + window._debugDataTileStateLayer.clearLayers(); +} + +window.debugCreateTile = function(qk,bounds) { + var s = {color: '#888', weight: 3, opacity: 0.7, fillColor: '#888', fillOpacity: 0.4, clickable: false}; + + bounds = new L.LatLngBounds(bounds); + bounds = bounds.pad(-0.02); + + var l = L.rectangle(bounds,s); + window._debugDataTileIdToRectangle[qk] = l; + window._debugDataTileStateLayer.addLayer(l); +} + +window.debugSetTileColour = function(qk,bordercol,fillcol) { + var l = window._debugDataTileIdToRectangle[qk]; + if (l) { + var s = {color: bordercol, weight: 3, opacity: 0.3, fillColor: fillcol, fillOpacity: 0.1, clickable: false}; + l.setStyle(s); + } +} + + +// cache for data tiles. indexed by the query key (qk) +window._requestCache = {} + +// cache entries older than the fresh age, and younger than the max age, are stale. they're used in the case of an error from the server +window.REQUEST_CACHE_FRESH_AGE = 60; // if younger than this, use data in the cache rather than fetching from the server +window.REQUEST_CACHE_MAX_AGE = 60*60; // maximum cache age. entries are deleted from the cache after this time +window.REQUEST_CACHE_MIN_SIZE = 200; // if fewer than this many entries, don't expire any +window.REQUEST_CACHE_MAX_SIZE = 2000; // if more than this many entries, expire early + +window.storeDataCache = function(qk,data) { + // 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 window._requestCache[qk]; + + var d = new Date(); + window._requestCache[qk] = { time: d.getTime(), data: data }; +} + +window.getDataCache = function(qk) { + if (qk in window._requestCache) { + return window._requestCache[qk].data; + } + return undefined; +} + +window.isDataCacheFresh = function(qk) { + if (qk in window._requestCache) { + var d = new Date(); + var t = d.getTime()-REQUEST_CACHE_FRESH_AGE*1000; + if (window._requestCache[qk].time > t) { + return true; + } + } + return false; +} + +window.expireDataCache = function() { + var d = new Date(); + var t = d.getTime()-window.REQUEST_CACHE_MAX_AGE*1000; + + var cacheSize = Object.keys(window._requestCache).length; + + for(var qk in window._requestCache) { + // stop processing once we hit the minimum size + if (cacheSize < window.REQUEST_CACHE_MIN_SIZE) break; + + // fixme? our MAX_SIZE test here assumes we're processing the oldest first. this relies + // on looping over object properties in the order they were added. this is true in most browsers, + // but is not a requirement of the standards + if (cacheSize > window.REQUEST_CACHE_MAX_SIZE || window._requestCache[qk].time < t) { + delete window._requestCache[qk]; + cacheSize--; + } + } + +} + // requests map data for current viewport. For details on how this // works, refer to the description in “MAP DATA REQUEST CALCULATORS” @@ -11,14 +102,27 @@ window.requestData = function() { console.log('refreshing data'); requests.abort(); cleanUp(); + window.statusTotalMapTiles = 0; + window.statusCachedMapTiles = 0; + window.statusSuccessMapTiles = 0; + window.statusStaleMapTiles = 0; + window.statusErrorMapTiles = 0; + + + debugDataTileReset(); + + expireDataCache(); //a limit on the number of map tiles to be pulled in a single request - var MAX_TILES_PER_BUCKET = 20; + var MAX_TILES_PER_BUCKET = 11; + // the number of separate buckets. more can be created if the size exceeds MAX_TILES_PER_BUCKET + var BUCKET_COUNT = 4; var bounds = clampLatLngBounds(map.getBounds()); //we query the server as if the zoom level was this. it may not match the actual map zoom level var z = getPortalDataZoom(); + console.log('requesting data tiles at zoom '+z+' (L'+getMinPortalLevelForZoom(z)+'+ portals), map zoom is '+map.getZoom()); var x1 = lngToTile(bounds.getWest(), z); var x2 = lngToTile(bounds.getEast(), z); @@ -29,45 +133,114 @@ window.requestData = function() { tiles = {}; fullBucketCount = 0; + var cachedData = { result: { map: {} } }; + var requestTileCount = 0; + // walk in x-direction, starts right goes left for (var x = x1; x <= x2; x++) { for (var y = y1; y <= y2; y++) { var tile_id = pointToTileId(z, x, y); - var bucket = (x % 2) + ":" + (y % 2); - if (!tiles[bucket]) { - //create empty bucket - tiles[bucket] = []; - } - else if(tiles[bucket].length >= MAX_TILES_PER_BUCKET) { - //too many items in bucket. rename it, and create a new empty one - tiles[bucket+'_'+fullBucketCount] = tiles[bucket]; - fullBucketCount++; - tiles[bucket] = []; + var latNorth = tileToLat(y,z); + var latSouth = tileToLat(y+1,z); + var lngWest = tileToLng(x,z); + var lngEast = tileToLng(x+1,z); + + debugCreateTile(tile_id,[[latSouth,lngWest],[latNorth,lngEast]]); + window.statusTotalMapTiles++; + + // TODO?: if the selected portal is in this tile, always fetch the data + if (isDataCacheFresh(tile_id)) { + // TODO: don't add tiles from the cache when 1. they were fully visible before, and 2. the zoom level is unchanged + // TODO?: if a closer zoom level has all four tiles in the cache, use them instead? + cachedData.result.map[tile_id] = getDataCache(tile_id); + debugSetTileColour(tile_id,'#0f0','#ff0'); + window.statusCachedMapTiles++; + } else { + // group requests into buckets based on the tile coordinate. + var bucket = Math.floor(x+y*(BUCKET_COUNT/2))%BUCKET_COUNT; + + if (!tiles[bucket]) { + //create empty bucket + tiles[bucket] = []; + } + else if(tiles[bucket].length >= MAX_TILES_PER_BUCKET) { + //too many items in bucket. rename it, and create a new empty one + tiles[bucket+'_'+fullBucketCount] = tiles[bucket]; + fullBucketCount++; + tiles[bucket] = []; + } + + requestTileCount++; + + var boundsParam = generateBoundsParams( + tile_id, + latSouth, + lngWest, + latNorth, + lngEast + ); + + // when the server is returning 'timeout' errors for some tiles in the list, it's always the tiles + // at the end of the request. therefore, let's push tiles we don't have cache entries for to the front, and those we do to the back + if (getDataCache(tile_id)) { + // cache entry exists - push to back + tiles[bucket].push(boundsParam); + } else { + // no cache entry - unshift to front + tiles[bucket].unshift(boundsParam); + } + + debugSetTileColour(tile_id,'#00f','#000'); } - tiles[bucket].push(generateBoundsParams( - tile_id, - tileToLat(y + 1, z), - tileToLng(x, z), - tileToLat(y, z), - tileToLng(x + 1, z) - )); } } // Reset previous result of Portal Render Limit handler portalRenderLimit.init(); - // finally send ajax requests + // send ajax requests + console.log('requesting '+requestTileCount+' tiles in '+Object.keys(tiles).length+' requests'); $.each(tiles, function(ind, tls) { data = { zoom: z }; data.boundsParamsList = tls; - window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, window.handleFailedRequest)); + // keep a list of tile_ids with each request. in the case of a server error, we can try and use cached tiles if available + var tile_ids = [] + $.each(tls,function(i,req) { tile_ids.push(req.qk); }); + window.requests.add(window.postAjax('getThinnedEntitiesV2', data, function(data, textStatus, jqXHR) { window.handleDataResponse(data,false,tile_ids); }, function() { window.handleFailedRequest(tile_ids); })); }); + + // process the requests from the cache + console.log('got '+Object.keys(cachedData.result.map).length+' data tiles from cache'); + if(Object.keys(cachedData.result.map).length > 0) { + handleDataResponse(cachedData, true); + } + } // Handle failed map data request -window.handleFailedRequest = function() { +window.handleFailedRequest = function(tile_ids) { + console.log('request failed: tiles '+tile_ids.join(',')); + + var cachedData = { result: { map: {} } }; + $.each(tile_ids, function(ind,tile_id) { + var cached = getDataCache(tile_id); + if (cached) { + // we have stale cached data - use it + cachedData.result.map[tile_id] = cached; + debugSetTileColour(tile_id,'#800','#ff0'); + console.log('(using stale cache entry for map tile '+tile_id+')'); + window.statusStaleMapTiles++; + } else { + // no cached data + debugSetTileColour(tile_id,'#800','#f00'); + window.statusErrorMapTiles++; + } + }); + if(Object.keys(cachedData.result.map).length > 0) { + handleDataResponse(cachedData, true); + } + if(requests.isLastRequest('getThinnedEntitiesV2')) { var leftOverPortals = portalRenderLimit.mergeLowLevelPortals(null); handlePortalsRender(leftOverPortals); @@ -76,12 +249,12 @@ window.handleFailedRequest = function() { } // works on map data response and ensures entities are drawn/updated. -window.handleDataResponse = function(data, textStatus, jqXHR) { +window.handleDataResponse = function(data, fromCache, tile_ids) { // remove from active ajax queries list if(!data || !data.result) { window.failedRequestCount++; console.warn(data); - handleFailedRequest(); + handleFailedRequest(tile_ids); return; } @@ -94,8 +267,35 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { var ppp = {}; var p2f = {}; $.each(m, function(qk, val) { - if('error' in val) { - console.log('map data tile '+qk+' response error: '+val.error); + + // if this request wasn't from the cache, check it's status. store in the cache if good + // for debugging, we set the debug tile colours. cached tiles have colours set elsewhere so are not set here + if (!fromCache) { + + if('error' in val) { + console.log('map data tile '+qk+' response error: '+val.error); + + // try to use data in the cache, even if it's stale + var cacheVal = getDataCache(qk); + + if (!cacheVal) { + debugSetTileColour(qk, '#f00','#f00'); + // no data in cache for this tile. continue processing - it's possible it also has some valid data + window.statusErrorMapTiles++; + } else { + // stale cache entry exists - use it + val = cacheVal; + debugSetTileColour(qk, '#f00','#ff0'); + console.log('(using stale cache entry for map tile '+qk+')'); + window.statusStaleMapTiles++; + } + } else { + // not an error - store this tile into the cache + storeDataCache(qk,val); + debugSetTileColour(qk, '#0f0','#0f0'); + window.statusSuccessMapTiles++; + } + } $.each(val.deletedGameEntityGuids || [], function(ind, guid) { @@ -299,6 +499,32 @@ window.removeByGuid = function(guid) { } +// Separation of marker style setting from the renderPortal method +// Having this as a separate function allows subsituting alternate marker rendering (for plugins) +window.getMarker = function(ent, portalLevel, latlng, team) { + var lvWeight = Math.max(2, Math.floor(portalLevel) / 1.5); + var lvRadius = Math.floor(portalLevel) + 4; + if(team === window.TEAM_NONE) { + lvRadius = 7; + } + + var p = L.circleMarker(latlng, { + radius: lvRadius + (L.Browser.mobile ? PORTAL_RADIUS_ENLARGE_MOBILE : 0), + color: ent[0] === selectedPortal ? COLOR_SELECTED_PORTAL : COLORS[team], + opacity: 1, + weight: lvWeight, + fillColor: COLORS[team], + fillOpacity: 0.5, + clickable: true, + level: portalLevel, + team: team, + ent: ent, + details: ent[2], + guid: ent[0]}); + + return p; +} + // renders a portal on the map from the given entity window.renderPortal = function(ent) { @@ -347,25 +573,7 @@ window.renderPortal = function(ent) { // pre-loads player names for high zoom levels loadPlayerNamesForPortal(ent[2]); - var lvWeight = Math.max(2, Math.floor(portalLevel) / 1.5); - var lvRadius = Math.floor(portalLevel) + 4; - if(team === window.TEAM_NONE) { - lvRadius = 7; - } - - var p = L.circleMarker(latlng, { - radius: lvRadius + (L.Browser.mobile ? PORTAL_RADIUS_ENLARGE_MOBILE : 0), - color: ent[0] === selectedPortal ? COLOR_SELECTED_PORTAL : COLORS[team], - opacity: 1, - weight: lvWeight, - fillColor: COLORS[team], - fillOpacity: 0.5, - clickable: true, - level: portalLevel, - team: team, - ent: ent, - details: ent[2], - guid: ent[0]}); + var p = getMarker(ent, portalLevel, latlng, team); p.on('remove', function() { var portalGuid = this.options.guid diff --git a/code/panes.js b/code/panes.js index 99ffdc59..cea82b51 100644 --- a/code/panes.js +++ b/code/panes.js @@ -2,6 +2,9 @@ // window.show = function(id) { window.hideall(); + if (typeof android !== 'undefined' && android && android.switchToPane) { + android.switchToPane(id); + } switch(id) { case 'full': window.chat.show('full'); diff --git a/code/player_names.js b/code/player_names.js index 1ad0183c..ab7f247d 100644 --- a/code/player_names.js +++ b/code/player_names.js @@ -80,7 +80,11 @@ window.resolvePlayerNames = function() { } -window.setPlayerName = function(guid, nick) { +window.setPlayerName = function(guid, nick, uncertain) { + // the 'uncertain' flag is set when we're scrolling back through chat. it's possible in this case + // to come across a message from before a name change. these should be ignored if existing cache entries exist + if(uncertain && guid in localStorage) return; + if($.trim(('' + nick)).slice(0, 5) === '{"L":' && !window.alertFor37WasShown) { window.alertFor37WasShown = true; 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)); diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js index c3ba306b..cb2e79a7 100644 --- a/code/portal_detail_display.js +++ b/code/portal_detail_display.js @@ -50,6 +50,41 @@ window.renderPortalDetails = function(guid) { var perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng; var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."'; var poslinks = 'window.showPortalPosLinks('+lat+','+lng+',\''+escapeJavascriptString(d.portalV2.descriptiveText.TITLE)+'\')'; + var portalDetailObj = window.getPortalDescriptionFromDetailsExtended(d); + + + var portalDetailedDescription = ''; + + if(portalDetailObj) { + portalDetailedDescription = ''; + + // TODO (once the data supports it) - portals can have multiple photos. display all, with navigation between them + // (at this time the data isn't returned from the server - although a count of images IS returned!) + + if(portalDetailObj.submitter.name.length > 0) { + if(portalDetailObj.submitter.team) { + submitterSpan = ''; + } else { + submitterSpan = ''; + } + portalDetailedDescription += ''; + } + if(portalDetailObj.submitter.link.length > 0) { + portalDetailedDescription += ''; + } + + if(portalDetailObj.description) { + portalDetailedDescription += ''; + } +// if(d.portalV2.descriptiveText.ADDRESS) { +// portalDetailedDescription += ''; +// } + + portalDetailedDescription += '
Photo by:' + submitterSpan + + escapeHtmlSpecialChars(portalDetailObj.submitter.name) + ' (' + portalDetailObj.submitter.voteCount + ' votes)
Photo from:' + escapeHtmlSpecialChars(portalDetailObj.submitter.link) + '
Description:' + escapeHtmlSpecialChars(portalDetailObj.description) + '
Address:' + escapeHtmlSpecialChars(d.portalV2.descriptiveText.ADDRESS) + '
'; + } + $('#portaldetails') .attr('class', TEAM_TO_CSS[getTeam(d)]) @@ -58,8 +93,9 @@ window.renderPortalDetails = function(guid) { + 'X' // help cursor via ".imgpreview img" + '
' - + '' + ''+Math.floor(getPortalLevel(d))+'' + + '
'+ portalDetailedDescription + '
' + + '
' + '
' + '
'+getModDetails(d)+'
' + randDetails @@ -129,5 +165,9 @@ window.unselectOldPortal = function() { if(oldPortal) portalResetColor(oldPortal); selectedPortal = null; $('#portaldetails').html(''); + if(isSmartphone()) { + $('.fullimg').remove(); + $('#mobileinfo').html(''); + } clearPortalIndicators(); } diff --git a/code/portal_detail_display_tools.js b/code/portal_detail_display_tools.js index 446f141f..085887cc 100644 --- a/code/portal_detail_display_tools.js +++ b/code/portal_detail_display_tools.js @@ -8,8 +8,8 @@ window.getRangeText = function(d) { return ['range', '' + (range > 1000 - ? Math.round(range/1000) + ' km' - : Math.round(range) + ' m') + ? Math.floor(range/1000) + ' km' + : Math.floor(range) + ' m') + '']; } @@ -23,6 +23,43 @@ window.getPortalDescriptionFromDetails = function(details) { return desc; } +// Grabs more info, including the submitter name for the current main +// portal image +window.getPortalDescriptionFromDetailsExtended = function(details) { + var descObj = details.portalV2.descriptiveText; + var photoStreamObj = details.photoStreamInfo; + + var submitterObj = new Object(); + submitterObj.type = ""; + submitterObj.name = "Unknown"; + submitterObj.team = ""; + submitterObj.link = ""; + submitterObj.voteCount = 0; + + if(photoStreamObj && photoStreamObj.hasOwnProperty("coverPhoto") && photoStreamObj.coverPhoto.hasOwnProperty("attributionMarkup")) { + var attribution = photoStreamObj.coverPhoto.attributionMarkup; + submitterObj.type = attribution[0]; + if(attribution[1].hasOwnProperty("plain")) + submitterObj.name = attribution[1].plain; + if(attribution[1].hasOwnProperty("team")) + submitterObj.team = attribution[1].team; + if(attribution[1].hasOwnProperty("attributionLink")) + submitterObj.link = attribution[1].attributionLink; + if(photoStreamObj.coverPhoto.hasOwnProperty("voteCount")) + submitterObj.voteCount = photoStreamObj.coverPhoto.voteCount; + } + + + var portalDetails = { + title: descObj.TITLE, + description: descObj.DESCRIPTION, + address: descObj.ADDRESS, + submitter: submitterObj + }; + + return portalDetails; +} + // given portal details, returns html code to display mod details. window.getModDetails = function(d) { @@ -30,29 +67,61 @@ window.getModDetails = function(d) { var modsTitle = []; var modsColor = []; $.each(d.portalV2.linkedModArray, function(ind, mod) { - if(!mod) { - mods.push(''); - modsTitle.push(''); - modsColor.push('#000'); - } else if(mod.type === 'RES_SHIELD') { + var modName = ''; + var modTooltip = ''; + var modColor = '#000'; - var title = mod.rarity.capitalize() + ' ' + mod.displayName + '\n'; - title += 'Installed by: '+ getPlayerName(mod.installingUser); + if (mod) { + // all mods seem to follow the same pattern for the data structure + // but let's try and make this robust enough to handle possible future differences - title += '\nStats:'; - for (var key in mod.stats) { - if (!mod.stats.hasOwnProperty(key)) continue; - title += '\n+' + mod.stats[key] + ' ' + key.capitalize(); + if (mod.displayName) { + modName = mod.displayName; + } else if (mod.type) { + modName = mod.type; + } else { + modName = '(unknown mod)'; } - mods.push(mod.rarity.capitalize().replace('_', ' ') + ' ' + mod.displayName); - modsTitle.push(title); - modsColor.push(COLORS_MOD[mod.rarity]); - } else { - mods.push(mod.type); - modsTitle.push('Unknown mod. No further details available.'); - modsColor.push('#FFF'); + if (mod.rarity) { + modName = mod.rarity.capitalize().replace(/_/g,' ') + ' ' + modName; + } + + modTooltip = modName + '\n'; + if (mod.installingUser) { + modTooltip += 'Installed by: '+ getPlayerName(mod.installingUser) + '\n'; + } + + if (mod.stats) { + modTooltip += 'Stats:'; + for (var key in mod.stats) { + if (!mod.stats.hasOwnProperty(key)) continue; + var val = mod.stats[key]; + + if (key === 'REMOVAL_STICKINESS' && val == 0) continue; // stat on all mods recently - unknown meaning, not displayed in stock client + + // special formatting for known mod stats, where the display of the raw value is less useful + if (mod.type === 'HEATSINK' && key === 'HACK_SPEED') val = (val/10000)+'%'; // 500000 = 50% + else if (mod.type === 'FORCE_AMP' && key === 'FORCE_AMPLIFIER') val = (val/1000)+'x'; // 2000 = 2x + else if (mod.type === 'LINK_AMPLIFIER' && key === 'LINK_RANGE_MULTIPLIER') val = (val/1000)+'x' // 2000 = 2x + else if (mod.type === 'TURRET' && key === 'HIT_BONUS') val = (val/10000)+'%'; // 2000 = 0.2% (although this seems pretty small to be useful?) + else if (mod.type === 'TURRET' && key === 'ATTACK_FREQUENCY') val = (val/1000)+'x' // 2000 = 2x + // else display unmodified. correct for shield mitigation and multihack - unknown for future/other mods + + modTooltip += '\n+' + val + ' ' + key.capitalize().replace(/_/g,' '); + } + } + + if (mod.rarity) { + modColor = COLORS_MOD[mod.rarity]; + } else { + modColor = '#fff'; + } } + + mods.push(modName); + modsTitle.push(modTooltip); + modsColor.push(modColor); }); var t = ''+mods[0]+'' diff --git a/code/portal_info.js b/code/portal_info.js index f414c2c9..6772effb 100644 --- a/code/portal_info.js +++ b/code/portal_info.js @@ -54,9 +54,39 @@ window.getPortalRange = function(d) { lvl += parseInt(reso.level); }); if(resoMissing) return 0; - return 160*Math.pow(getPortalLevel(d), 4); + + var range = 160*Math.pow(getPortalLevel(d), 4); + + var boost = getLinkAmpRangeBoost(d); + + return range*boost; + } +window.getLinkAmpRangeBoost = function(d) { + // additional range boost calculation + // (at the time of writing, only rare link amps have been seen in the wild, so there's a little guesswork at how + // the stats work and combine - jon 2013-06-26) + + // link amps scale: first is full, second half, the last two a quarter + var scale = [1.0, 0.5, 0.25, 0.25]; + + var boost = 1.0; // initial boost is 1.0 (i.e. no boost over standard range) + var count = 0; + + $.each(d.portalV2.linkedModArray, function(ind, mod) { + if(mod && mod.type === 'LINK_AMPLIFIER' && mod.stats && mod.stats.LINK_RANGE_MULTIPLIER) { + // link amp stat LINK_RANGE_MULTIPLIER is 2000 for rare, and gives 2x boost to the range + var baseMultiplier = mod.stats.LINK_RANGE_MULTIPLIER/1000; + boost += (baseMultiplier-1)*scale[count]; + count++; + } + }); + + return boost; +} + + window.getAvgResoDist = function(d) { var sum = 0, resos = 0; $.each(d.resonatorArray.resonators, function(ind, reso) { diff --git a/code/redeeming.js b/code/redeeming.js index 528aa084..eb613048 100644 --- a/code/redeeming.js +++ b/code/redeeming.js @@ -18,6 +18,36 @@ window.REDEEM_RESOURCES = { return {long: 'Portal Shield', short: 'S'}; } }, + FORCE_AMP: { + format: function(acquired) { + return {long: 'Force Amp', short: 'FA'}; + } + }, + LINK_AMP: { + format: function(acquired) { + return {long: 'Link Amp', short: 'LA'}; + } + }, + HEATSINK: { + format: function(acquired) { + return {long: 'Heatsink', short: 'H'}; + } + }, + MULTIHACK: { + format: function(acquired) { + return {long: 'Multihack', short: 'M'}; + } + }, + TURRET: { + format: function(acquired) { + return {long: 'Turret', short: 'T'}; + } + }, + UNUSUAL: { + format: function(acquired) { + return {long: 'Unusual Object', short: 'U'}; + } + }, EMITTER_A: { /* resourceWithLevels */ format: function(acquired) { diff --git a/code/request_handling.js b/code/request_handling.js index b77a29ba..3919bcdb 100644 --- a/code/request_handling.js +++ b/code/request_handling.js @@ -5,6 +5,12 @@ window.activeRequests = []; window.failedRequestCount = 0; +window.statusTotalMapTiles = 0; +window.statusCachedMapTiles = 0; +window.statusSuccessMapTiles = 0; +window.statusStaleMapTiles = 0; +window.statusErrorMapTiles = 0; + window.requests = function() {} @@ -39,7 +45,7 @@ window.requests.abort = function() { // to website. Updates info in layer chooser. window.renderUpdateStatus = function() { - var t = '
portals: '; + var t = 'portals: '; var minlvl = getMinPortalLevel(); if(minlvl === 0) t += 'all'; @@ -52,12 +58,22 @@ window.renderUpdateStatus = function() { t += 'paused 0) - t += window.activeRequests.length + ' requests'; else if(window.requests._quickRefreshPending) t += 'refreshing'; - else - t += 'Up to date'; + else if(window.activeRequests.length > 0) + t += window.activeRequests.length + ' requests'; + else { + // tooltip with detailed tile counts + t += ''; + + // basic error/out of date/up to date message + if (window.statusErrorMapTiles) t += 'Errors'; + else if (window.statusStaleMapTiles) t += 'Out of date'; + else t += 'Up to date'; + + t += ''; + + } t += ''; if(renderLimitReached()) @@ -66,8 +82,6 @@ window.renderUpdateStatus = function() { if(window.failedRequestCount > 0) t += ' ' + window.failedRequestCount + ' failed' - t += '
'; - 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 @@ -76,7 +90,7 @@ window.renderUpdateStatus = function() { portalSelection.slice(minlvl, 8+1).removeClass('disabled').attr('title', ''); - $('#updatestatus').html(t); + $('#innerstatus').html(t); //$('#updatestatus').click(function() { startRefreshTimeout(10); }); //. '; } @@ -120,7 +134,7 @@ window.requests._callOnRefreshFunctions = function() { startRefreshTimeout(); if(isIdle()) { - console.log('user has been idle for ' + idleTime + ' minutes. Skipping refresh.'); + console.log('user has been idle for ' + idleTime + ' seconds, or window hidden. Skipping refresh.'); renderUpdateStatus(); return; } diff --git a/code/smartphone.js b/code/smartphone.js index 59acb7af..9d913c22 100644 --- a/code/smartphone.js +++ b/code/smartphone.js @@ -68,12 +68,30 @@ window.runOnSmartphonesBeforeBoot = function() { }); } +window.smartphoneInfo = function(data) { + var d = data.portalDetails; + var t = 'L' + Math.floor(getPortalLevel(d)); + var percentage = '0%'; + var totalEnergy = getTotalPortalEnergy(d); + if(getTotalPortalEnergy(d) > 0) { + percentage = Math.floor((getCurrentPortalEnergy(d) / getTotalPortalEnergy(d) * 100)) + '%'; + } + t += ' ' + percentage + ' '; + t += d.portalV2.descriptiveText.TITLE; + + $('#mobileinfo').html(t); +} + window.runOnSmartphonesAfterBoot = function() { if(!isSmartphone()) return; console.warn('running smartphone post boot stuff'); smartphone.mapButton.click(); + // add a div/hook for updating mobile info + $('#updatestatus').prepend('
'); + window.addHook('portalDetailsUpdated', window.smartphoneInfo); + // disable img full view $('#portaldetails').off('click', '**'); @@ -90,12 +108,8 @@ window.runOnSmartphonesAfterBoot = function() { // this is a hack, accessing Leaflet’s private _container is evil $(this._container).on('taphold', function() { - if (typeof android !== 'undefined' && android && android.portalLongPressed) { - android.portalLongPressed(); - } else { - window.renderPortalDetails(guid); - window.smartphone.sideButton.click(); - } + window.renderPortalDetails(guid); + window.show('info'); }); }); }); diff --git a/code/utils_misc.js b/code/utils_misc.js index 91147c1b..781fd378 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -249,23 +249,20 @@ window.getPortalDataZoom = function() { // 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?) - // a potential downside - we end up requesting more data than we needed from the larger tiles that go off - // the window edge. + // very effective along with the new cache code if (z > 17) z=17; // we could consider similar zoom-level consolidation, as, e.g. level 16 and 15 both return L1+, always // request zoom 15 tiles. however, there are quirks in the current data stream, where small fields aren't // returned by the server. using larger tiles always would amplify this issue. - //sanity check - should never happen if (z < 0) z=0; return z; } -window.getMinPortalLevel = function() { - var z = getPortalDataZoom(); +window.getMinPortalLevelForZoom = function(z) { if(z >= 17) return 0; if(z < 0) return 8; var conv = [8,8,8,8,7,7,6,6,5,4,4,3,3,2,2,1,1]; @@ -276,6 +273,12 @@ window.getMinPortalLevel = function() { return result; } + +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) { diff --git a/external/Control.MiniMap.css b/external/Control.MiniMap.css new file mode 100644 index 00000000..c558467f --- /dev/null +++ b/external/Control.MiniMap.css @@ -0,0 +1,31 @@ +.leaflet-control-minimap { + border:solid rgba(255, 255, 255, 0.7) 3px; + box-shadow: 0 1px 7px #999; + background: #f8f8f9; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} + +.leaflet-control-minimap a { + background-color: rgba(255, 255, 255, 0.75); + background-position: 1px 2px; + background-repeat: no-repeat; + display: block; + outline: none; + z-index: 99999; +} + +.leaflet-control-minimap a.minimized { + background-position: 1px -18px; +} + +.leaflet-control-minimap-toggle-display { + background-image: url(@@INCLUDEIMAGE:images/minimap-toggle.png@@); + border-radius: 4px 4px 4px 4px; + height: 19px; + width: 19px; + position: absolute; + bottom: 0; + right: 0; +} diff --git a/external/Control.MiniMap.js b/external/Control.MiniMap.js new file mode 100644 index 00000000..db912307 --- /dev/null +++ b/external/Control.MiniMap.js @@ -0,0 +1,243 @@ +L.Control.MiniMap = L.Control.extend({ + options: { + position: 'bottomright', + toggleDisplay: false, + zoomLevelOffset: -5, + zoomLevelFixed: false, + zoomAnimation: false, + autoToggleDisplay: false, + width: 150, + height: 150 + }, + + hideText: 'Hide MiniMap', + + showText: 'Show MiniMap', + + //layer is the map layer to be shown in the minimap + initialize: function (layer, options) { + L.Util.setOptions(this, options); + this._layer = layer; + }, + + onAdd: function (map) { + + this._mainMap = map; + + //Creating the container and stopping events from spilling through to the main map. + this._container = L.DomUtil.create('div', 'leaflet-control-minimap'); + this._container.style.width = this.options.width + 'px'; + this._container.style.height = this.options.height + 'px'; + L.DomEvent.disableClickPropagation(this._container); + L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation); + + + this._miniMap = new L.Map(this._container, + { + attributionControl: false, + zoomControl: false, + zoomAnimation: this.options.zoomAnimation, + autoToggleDisplay: this.options.autoToggleDisplay, + touchZoom: !this.options.zoomLevelFixed, + scrollWheelZoom: !this.options.zoomLevelFixed, + doubleClickZoom: !this.options.zoomLevelFixed, + boxZoom: !this.options.zoomLevelFixed, + crs: map.options.crs + }); + + this._miniMap.addLayer(this._layer); + + //These bools are used to prevent infinite loops of the two maps notifying each other that they've moved. + this._mainMapMoving = false; + this._miniMapMoving = false; + + //Keep a record of this to prevent auto toggling when the user explicitly doesn't want it. + this._userToggledDisplay = false; + this._minimized = false; + + if (this.options.toggleDisplay) { + this._addToggleButton(); + } + + this._miniMap.whenReady(L.Util.bind(function () { + this._aimingRect = L.rectangle(this._mainMap.getBounds(), {color: "#ff7800", weight: 1, clickable: false}).addTo(this._miniMap); + this._shadowRect = L.rectangle(this._mainMap.getBounds(), {color: "#000000", weight: 1, clickable: false,opacity:0,fillOpacity:0}).addTo(this._miniMap); + this._mainMap.on('moveend', this._onMainMapMoved, this); + this._mainMap.on('move', this._onMainMapMoving, this); + this._miniMap.on('movestart', this._onMiniMapMoveStarted, this); + this._miniMap.on('move', this._onMiniMapMoving, this); + this._miniMap.on('moveend', this._onMiniMapMoved, this); + }, this)); + + return this._container; + }, + + addTo: function (map) { + L.Control.prototype.addTo.call(this, map); + this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true)); + this._setDisplay(this._decideMinimized()); + return this; + }, + + onRemove: function (map) { + this._mainMap.off('moveend', this._onMainMapMoved, this); + this._mainMap.off('move', this._onMainMapMoving, this); + this._miniMap.off('moveend', this._onMiniMapMoved, this); + + this._miniMap.removeLayer(this._layer); + }, + + _addToggleButton: function () { + this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton( + '', this.hideText, 'leaflet-control-minimap-toggle-display', this._container, this._toggleDisplayButtonClicked, this) : undefined; + }, + + _createButton: function (html, title, className, container, fn, context) { + var link = L.DomUtil.create('a', className, container); + link.innerHTML = html; + link.href = '#'; + link.title = 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', fn, context); + + return link; + }, + + _toggleDisplayButtonClicked: function () { + this._userToggledDisplay = true; + if (!this._minimized) { + this._minimize(); + this._toggleDisplayButton.title = this.showText; + } + else { + this._restore(); + this._toggleDisplayButton.title = this.hideText; + } + }, + + _setDisplay: function (minimize) { + if (minimize != this._minimized) { + if (!this._minimized) { + this._minimize(); + } + else { + this._restore(); + } + } + }, + + _minimize: function () { + // hide the minimap + if (this.options.toggleDisplay) { + this._container.style.width = '19px'; + this._container.style.height = '19px'; + this._toggleDisplayButton.className += ' minimized'; + } + else { + this._container.style.display = 'none'; + } + this._minimized = true; + }, + + _restore: function () { + if (this.options.toggleDisplay) { + this._container.style.width = this.options.width + 'px'; + this._container.style.height = this.options.height + 'px'; + this._toggleDisplayButton.className = this._toggleDisplayButton.className + .replace(/(?:^|\s)minimized(?!\S)/g, ''); + } + else { + this._container.style.display = 'block'; + } + this._minimized = false; + }, + + _onMainMapMoved: function (e) { + if (!this._miniMapMoving) { + this._mainMapMoving = true; + this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true)); + this._setDisplay(this._decideMinimized()); + } else { + this._miniMapMoving = false; + } + this._aimingRect.setBounds(this._mainMap.getBounds()); + }, + + _onMainMapMoving: function (e) { + this._aimingRect.setBounds(this._mainMap.getBounds()); + }, + + _onMiniMapMoveStarted:function (e) { + var lastAimingRect = this._aimingRect.getBounds(); + var sw = this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest()); + var ne = this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast()); + this._lastAimingRectPosition = {sw:sw,ne:ne}; + }, + + _onMiniMapMoving: function (e) { + if (!this._mainMapMoving && this._lastAimingRectPosition) { + this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw),this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne))); + this._shadowRect.setStyle({opacity:1,fillOpacity:0.3}); + } + }, + + _onMiniMapMoved: function (e) { + if (!this._mainMapMoving) { + this._miniMapMoving = true; + this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false)); + this._shadowRect.setStyle({opacity:0,fillOpacity:0}); + } else { + this._mainMapMoving = false; + } + }, + + _decideZoom: function (fromMaintoMini) { + if (!this.options.zoomLevelFixed) { + if (fromMaintoMini) + return this._mainMap.getZoom() + this.options.zoomLevelOffset; + else + return this._miniMap.getZoom() - this.options.zoomLevelOffset; + } else { + if (fromMaintoMini) + return this.options.zoomLevelFixed; + else + return this._mainMap.getZoom(); + } + }, + + _decideMinimized: function () { + if (this._userToggledDisplay) { + return this._minimized; + } + + if (this.options.autoToggleDisplay) { + if (this._mainMap.getBounds().contains(this._miniMap.getBounds())) { + return true; + } + return false; + } + + return this._minimized; + } +}); + +L.Map.mergeOptions({ + miniMapControl: false +}); + +L.Map.addInitHook(function () { + if (this.options.miniMapControl) { + this.miniMapControl = (new L.Control.MiniMap()).addTo(this); + } +}); + +L.control.minimap = function (options) { + return new L.Control.MiniMap(options); +}; diff --git a/external/delaunay.js b/external/delaunay.js index c4533930..e9ec5b4b 100644 --- a/external/delaunay.js +++ b/external/delaunay.js @@ -18,7 +18,7 @@ /* If the points of the triangle are collinear, then just find the * extremes and use the midpoint as the center of the circumcircle. */ - if(Math.abs(G) < 0.000001) { + if(Math.abs(G) < 1e-12) { minx = Math.min(a.x, b.x, c.x) miny = Math.min(a.y, b.y, c.y) dx = (Math.max(a.x, b.x, c.x) - minx) * 0.5 @@ -166,4 +166,4 @@ /* Yay, we're done! */ return closed - } \ No newline at end of file + } diff --git a/images/minimap-toggle.png b/images/minimap-toggle.png new file mode 100644 index 00000000..026d4c8b Binary files /dev/null and b/images/minimap-toggle.png differ diff --git a/main.js b/main.js index c39d2c61..5ee9ac47 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,7 @@ // ==UserScript== // @id ingress-intel-total-conversion@jonatkins // @name IITC: Ingress intel map total conversion -// @version 0.12.1.@@DATETIMEVERSION@@ +// @version 0.12.3.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -21,6 +21,7 @@ window.iitcBuildDate = '@@BUILDDATE@@'; // disable vanilla JS window.onload = function() {}; +document.body.onload = function() {}; // rescue user data from original page @@ -92,14 +93,15 @@ document.getElementsByTagName('body')[0].innerHTML = '' + ' ' + '
' + '
' - + ' ' +// redeeming removed from stock site, so commented out for now. it may return... +// + ' ' + '
' + ' Permalink' + ' About IITC' + '
' + ' ' + '' - + '
'; + + '
'; // 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 @@ -113,12 +115,12 @@ function wrapper() { L_PREFER_CANVAS = false; // CONFIG OPTIONS //////////////////////////////////////////////////// -window.REFRESH = 60; // refresh view every 60s (base time) +window.REFRESH = 30; // refresh view every 30s (base time) window.ZOOM_LEVEL_ADJ = 5; // add 5 seconds per zoom level window.ON_MOVE_REFRESH = 1.25; //refresh time to use after a movement event window.MINIMUM_OVERRIDE_REFRESH = 5; //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; // stop updating map after 4min idling +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; @@ -161,6 +163,8 @@ window.COLORS_MOD = {VERY_RARE: '#F78AF6', RARE: '#AD8AFF', COMMON: '#84FBBD'}; window.OPTIONS_RESONATOR_SELECTED = {color: '#fff', weight: 2, radius: 4, opacity: 1, clickable: false}; window.OPTIONS_RESONATOR_NON_SELECTED = {color: '#aaa', weight: 1, radius: 3, opacity: 1, clickable: false}; +window.MOD_TYPE = {RES_SHIELD:'Shield', MULTIHACK:'Multi-hack', FORCE_AMP:'Force Amp', HEATSINK:'Heat Sink', TURRET:'Turret', LINK_AMPLIFIER: 'Link Amp'}; + window.OPTIONS_RESONATOR_LINE_SELECTED = { opacity: 0.7, weight: 3, diff --git a/mobile/.idea/misc.xml b/mobile/.idea/misc.xml index e0d90dd8..1c9e3220 100644 --- a/mobile/.idea/misc.xml +++ b/mobile/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml index f535fe6b..54e0e1d7 100644 --- a/mobile/AndroidManifest.xml +++ b/mobile/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="30" + android:versionName="0.4.9"> - - - - - diff --git a/mobile/user-location.user.js b/mobile/plugins/user-location.user.js similarity index 71% rename from mobile/user-location.user.js rename to mobile/plugins/user-location.user.js index ce2f0631..6bdf28f7 100644 --- a/mobile/user-location.user.js +++ b/mobile/plugins/user-location.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-user-location@cradle // @name IITC plugin: User Location -// @version 0.1.0.@@DATETIMEVERSION@@ +// @version 0.1.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -12,10 +12,7 @@ // @match http://www.ingress.com/intel* // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -34,10 +31,21 @@ window.plugin.userLocation.setup = function() { iconRetinaUrl: iconRetImage }}); + var cssClass = PLAYER.team === 'ALIENS' ? 'enl' : 'res'; + var title = '' + PLAYER.nickname + '\'s location'; + var marker = L.marker(window.map.getCenter(), { - title: "User Location", + title: title, icon: new plugin.userLocation.icon() }); + + // copy location to android clipboard on marker click + marker.on('click', function(e) { + window.console.log('marker location'); + var ll = e.target.getLatLng(); + window.androidCopy('https://maps.google.com/?q='+ll.lat+','+ll.lng+'%20('+PLAYER.nickname+')'); + }); + plugin.userLocation.marker = marker; marker.addTo(window.map); // jQueryUI doesn’t automatically notice the new markers @@ -53,16 +61,4 @@ var setup = window.plugin.userLocation.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/mobile/res/values/strings.xml b/mobile/res/values/strings.xml index 82119080..d486e60e 100644 --- a/mobile/res/values/strings.xml +++ b/mobile/res/values/strings.xml @@ -32,7 +32,7 @@ UI Misc - Plugins + IITC Plugins Available plugins Display user location Show users position on map @@ -44,11 +44,14 @@ Nice for tablets, looks awful on smartphones Force https Disabling may improve performance + Press back button twice to exit + Avoids accidental exits Developer options Enable developer mode 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/. IITC source + Load IITC main script from url or use local script. Currently used source: Chat Full diff --git a/mobile/res/xml/preferences.xml b/mobile/res/xml/preferences.xml index 57f2c2b7..a4b14c02 100644 --- a/mobile/res/xml/preferences.xml +++ b/mobile/res/xml/preferences.xml @@ -37,20 +37,24 @@ + - + + { } private Account mAccount; - private AccountAdapter mAccountAdapter; - private AccountManager mAccountManager; + private final AccountAdapter mAccountAdapter; + private final AccountManager mAccountManager; private Account[] mAccounts; - private IITC_Mobile mActivity; + private final IITC_Mobile mActivity; private String mAuthToken; - private AlertDialog mProgressbar; - private WebView mWebView; + private final AlertDialog mProgressbar; + private final WebView mWebView; /** - * This listener is invoked when an item in the account list is selected. (It is also used when the 'cancel' button - * is clicked, (in which case `index` is <0) + * This listener is invoked when an item in the account list is selected. + * (It is also used when the 'cancel' button is clicked, (in which case `index` is <0) */ - private DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int index) { - if (index >= 0 && index < mAccounts.length) { - mAccount = mAccounts[index]; - startAuthentication(); - } - dialog.cancel(); - } - }; + private final DialogInterface.OnClickListener onClickListener = + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int index) { + if (index >= 0 && index < mAccounts.length) { + mAccount = mAccounts[index]; + startAuthentication(); + } + dialog.cancel(); + } + }; - public IITC_DeviceAccountLogin(IITC_Mobile activity, WebView webView, WebViewClient webViewClient) { + public IITC_DeviceAccountLogin(IITC_Mobile activity, WebView webView, + WebViewClient webViewClient) { mActivity = activity; mWebView = webView; mAccountManager = AccountManager.get(activity); @@ -112,7 +114,7 @@ public class IITC_DeviceAccountLogin implements AccountManagerCallback { /** * called to start authenticating using AccountManager. - * + *

* After a token is created, AccountManager will call the run() method. */ private void startAuthentication() { @@ -142,16 +144,17 @@ public class IITC_DeviceAccountLogin implements AccountManagerCallback { try { Intent launch = (Intent) value.getResult().get(AccountManager.KEY_INTENT); if (launch != null) { - // There is a reason we need to start the given activity if we want an authentication token. - // (Could be user confirmation or something else. Whatever, we have to start it) - // IITC_Mobile will call it using startActivityForResult + // There is a reason we need to start the given activity if we want an + // authentication token. (Could be user confirmation or something else. Whatever, + // we have to start it) IITC_Mobile will call it using startActivityForResult mActivity.startLoginActivity(launch); return; } String result = value.getResult().getString(AccountManager.KEY_AUTHTOKEN); if (result != null) { - // authentication succeded, we can load the given url, which will redirect back to the intel map + // authentication succeded, we can load the given url, which will redirect + // back to the intel map mWebView.loadUrl(result); mActivity.loginSucceeded(); } else { @@ -164,9 +167,9 @@ public class IITC_DeviceAccountLogin implements AccountManagerCallback { /** * start authentication - * - * if we already have a username (e.g. because the existing login has timed out), we can directly start - * authentication if an account with that username is found. + *

+ * if we already have a username (e.g. because the existing login has timed out), + * we can directly start authentication if an account with that username is found. */ public void startLogin(String realm, String accountName, String args) { mAccounts = mAccountManager.getAccountsByType(realm); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java index 70011373..38771264 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java @@ -1,10 +1,5 @@ package com.cradle.iitc_mobile; -import java.util.HashMap; - -import org.json.JSONArray; -import org.json.JSONException; - import android.app.AlertDialog; import android.content.ClipData; import android.content.ClipboardManager; @@ -18,17 +13,22 @@ import android.util.Log; import android.webkit.JavascriptInterface; import android.widget.Toast; +import org.json.JSONArray; +import org.json.JSONException; + +import java.util.HashMap; + // provide communication between IITC script and android app public class IITC_JSInterface { // context of main activity - Context context; - HashMap layer_ids; - boolean[] overlay_is_active; - int active_base_layer; - String[] overlay_layers, base_layers; - int num_base_layers; - int num_overlay_layers; + private final Context context; + private final HashMap layer_ids; + private boolean[] overlay_is_active; + private int active_base_layer; + private String[] overlay_layers, base_layers; + private int num_base_layers; + private int num_overlay_layers; IITC_JSInterface(Context c) { layer_ids = new HashMap(); @@ -65,22 +65,68 @@ public class IITC_JSInterface { } @JavascriptInterface - public void portalLongPressed() { + public void switchToPane(String id) { + final IITC_Mobile iitcm = (IITC_Mobile) context; + final int button_id; + final String title; + + if (id.equals("map")) { + button_id = android.R.id.home; + title = iitcm.getString(R.string.app_name); + } else if (id.equals("info")) { + button_id = R.id.menu_info; + title = "Info"; + } else if (id.equals("full")) { + button_id = R.id.menu_full; + title = "Full"; + } else if (id.equals("compact")) { + button_id = R.id.menu_compact; + title = "Compact"; + } else if (id.equals("public")) { + button_id = R.id.menu_public; + title = "Public"; + } else if (id.equals("faction")) { + button_id = R.id.menu_faction; + title = "Faction"; + } else if (id.equals("debug")) { + button_id = R.id.menu_debug; + title = "Debug"; + } + // default + else { + button_id = android.R.id.home; + title = iitcm.getString(R.string.app_name); + } + + Log.d("iitcm", "switch to pane " + id); iitcm.runOnUiThread(new Runnable() { @Override public void run() { - iitcm.handleMenuItemSelected(R.id.menu_info, true); + iitcm.getActionBar().setTitle(title); + iitcm.backStackUpdate(button_id); } }); } + + @JavascriptInterface + public void dialogOpened(String id, boolean open) { + ((IITC_Mobile) context).dialogOpened(id, open); + } + + @JavascriptInterface + public void dialogFocused(String id) { + ((IITC_Mobile) context).setFocusedDialog(id); + } + // get layers and list them in a dialog @JavascriptInterface public void setLayers(String base_layer, String overlay_layer) { /* * the layer strings have a form like: - * [{"layerId":27,"name":"MapQuest OSM","active":true},{"layerId":28,"name":"Default Ingress Map","active":false}] + * [{"layerId":27,"name":"MapQuest OSM","active":true}, + * {"layerId":28,"name":"Default Ingress Map","active":false}] * Put it in a JSONArray and parse it */ JSONArray base_layersJSON = null; @@ -121,8 +167,8 @@ public class IITC_JSInterface { String id = ""; String name = ""; boolean isActive = false; - for (int j = 0; j < layers.length; ++j) { - String[] values = layers[j].split(":"); + for (String b_layer : layers) { + String[] values = b_layer.split(":"); if (values[0].contains("active")) isActive = values[1].equals("true"); if (values[0].contains("layerId")) id = values[1]; if (values[0].contains("name")) name = values[1]; @@ -147,8 +193,8 @@ public class IITC_JSInterface { String id = ""; String name = ""; boolean isActive = false; - for (int j = 0; j < layers.length; ++j) { - String[] values = layers[j].split(":"); + for (String o_layer : layers) { + String[] values = o_layer.split(":"); if (values[0].contains("active")) isActive = values[1].equals("true"); if (values[0].contains("layerId")) id = values[1]; if (values[0].contains("name")) name = values[1]; @@ -169,32 +215,33 @@ public class IITC_JSInterface { // show all overlay layers in a multi selection list dialog private void show_multi_selection() { // build the layer chooser dialog - AlertDialog.Builder d_m = new AlertDialog.Builder(context); + AlertDialog.Builder d_m = new AlertDialog.Builder(context); OnMultiChoiceClickListener m_listener = new OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { // activate clicked layer - ((IITC_Mobile) context).getWebView().loadUrl("javascript: window.layerChooser.showLayer(" + ((IITC_Mobile) context).getWebView().loadUrl("javascript: " + + "window.layerChooser.showLayer(" + layer_ids.get(overlay_layers[which]) + "," + overlay_is_active[which] + ");"); } }; - d_m.setMultiChoiceItems(overlay_layers, overlay_is_active , m_listener); + d_m.setMultiChoiceItems(overlay_layers, overlay_is_active, m_listener); // switch to base layers d_m.setPositiveButton("Base Layers", new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - show_single_selection(); - dialog.cancel(); - } + @Override + public void onClick(DialogInterface dialog, int which) { + show_single_selection(); + dialog.cancel(); + } }); d_m.setNegativeButton("Close", new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.cancel(); + } }); d_m.setTitle("Overlay Layers"); d_m.show(); @@ -206,11 +253,12 @@ public class IITC_JSInterface { @Override public void onClick(DialogInterface dialog, int which) { // activate clicked layer - ((IITC_Mobile) context).getWebView().loadUrl("javascript: window.layerChooser.showLayer(" + ((IITC_Mobile) context).getWebView().loadUrl("javascript: " + + "window.layerChooser.showLayer(" + layer_ids.get(base_layers[which]) + "," + true + ");"); active_base_layer = which; - } + } }; AlertDialog.Builder d_s = new AlertDialog.Builder(context); d_s.setSingleChoiceItems(base_layers, active_base_layer, s_listener); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java index 3c5c5339..65314542 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java @@ -1,8 +1,5 @@ package com.cradle.iitc_mobile; -import java.io.IOException; -import java.util.ArrayList; - import android.app.ActionBar; import android.app.Activity; import android.app.SearchManager; @@ -19,6 +16,7 @@ import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.os.StrictMode; import android.preference.PreferenceManager; import android.util.Log; @@ -26,18 +24,23 @@ import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.view.WindowManager; +import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.SearchView; import android.widget.Toast; +import java.io.IOException; +import java.util.ArrayList; + public class IITC_Mobile extends Activity { private static final int REQUEST_LOGIN = 1; private IITC_WebView iitc_view; private OnSharedPreferenceChangeListener listener; - private String intel_url = "https://www.ingress.com/intel"; - private boolean user_loc = false; + private final String intel_url = "https://www.ingress.com/intel"; + private boolean is_loc_enabled = false; + private Location last_location = null; private LocationManager loc_mngr = null; private LocationListener loc_listener = null; private boolean fullscreen_mode = false; @@ -47,10 +50,14 @@ public class IITC_Mobile extends Activity { private MenuItem searchMenuItem; private boolean desktop = false; private boolean reload_needed = false; + private final ArrayList dialogStack = new ArrayList(); + private SharedPreferences sharedPref; // Used for custom back stack handling - private ArrayList backStack = new ArrayList(); + private final ArrayList backStack = new ArrayList(); + private boolean backStack_push = true; private int currentPane = android.R.id.home; + private boolean back_button_pressed = false; @Override protected void onCreate(Bundle savedInstanceState) { @@ -59,10 +66,6 @@ public class IITC_Mobile extends Activity { // enable progress bar above action bar requestWindowFeature(Window.FEATURE_PROGRESS); - // TODO build an async task for url.openStream() in IITC_WebViewClient - StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() - .permitAll().build(); - StrictMode.setThreadPolicy(policy); setContentView(R.layout.activity_main); iitc_view = (IITC_WebView) findViewById(R.id.iitc_webview); @@ -75,7 +78,7 @@ public class IITC_Mobile extends Activity { actionBar.setHomeButtonEnabled(true); // do something if user changed something in the settings - SharedPreferences sharedPref = PreferenceManager + sharedPref = PreferenceManager .getDefaultSharedPreferences(this); listener = new OnSharedPreferenceChangeListener() { @Override @@ -86,12 +89,11 @@ public class IITC_Mobile extends Activity { if (desktop) { setActionBarHomeEnabledWithUp(false); actionBar.setTitle(getString(R.string.app_name)); - } - else actionBar.setHomeButtonEnabled(true); + } else actionBar.setHomeButtonEnabled(true); invalidateOptionsMenu(); } if (key.equals("pref_user_loc")) - user_loc = sharedPreferences.getBoolean("pref_user_loc", + is_loc_enabled = sharedPreferences.getBoolean("pref_user_loc", false); if (key.equals("pref_fullscreen_actionbar")) { fullscreen_actionbar = sharedPreferences.getBoolean("pref_fullscreen_actionbar", @@ -101,6 +103,10 @@ public class IITC_Mobile extends Activity { // no iitc reload needed here return; } + // no reload needed + if (key.equals("pref_press_twice_to_exit")) + return; + reload_needed = true; } }; @@ -119,6 +125,7 @@ public class IITC_Mobile extends Activity { // Called when a new location is found by the network location // provider. drawMarker(location); + last_location = location; } public void onStatusChanged(String provider, int status, @@ -132,8 +139,8 @@ public class IITC_Mobile extends Activity { } }; - user_loc = sharedPref.getBoolean("pref_user_loc", false); - if (user_loc == true) { + is_loc_enabled = sharedPref.getBoolean("pref_user_loc", false); + if (is_loc_enabled) { // Register the listener with the Location Manager to receive // location updates loc_mngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, @@ -163,8 +170,6 @@ public class IITC_Mobile extends Activity { if (Intent.ACTION_VIEW.equals(action)) { Uri uri = intent.getData(); String url = uri.toString(); - if (intent.getScheme().equals("http")) - url = url.replace("http://", "https://"); Log.d("iitcm", "intent received url: " + url); if (url.contains("ingress.com")) { Log.d("iitcm", "loading url..."); @@ -195,7 +200,7 @@ public class IITC_Mobile extends Activity { iitc_view.loadUrl("javascript: window.renderUpdateStatus()"); iitc_view.updateCaching(); - if (user_loc == true) { + if (is_loc_enabled) { // Register the listener with the Location Manager to receive // location updates loc_mngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, @@ -213,7 +218,8 @@ public class IITC_Mobile extends Activity { @Override protected void onStop() { - ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); + ConnectivityManager conMan = + (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mobile = conMan .getNetworkInfo(ConnectivityManager.TYPE_MOBILE); @@ -246,7 +252,7 @@ public class IITC_Mobile extends Activity { } Log.d("iitcm", "stopping iitcm"); - if (user_loc == true) + if (is_loc_enabled) loc_mngr.removeUpdates(loc_listener); super.onStop(); @@ -264,14 +270,37 @@ public class IITC_Mobile extends Activity { // we want a self defined behavior for the back button @Override public void onBackPressed() { - // exit fullscreen mode if it is enabled and action bar is disabled or the back stack is empty + // first kill all open iitc dialogs + if (!dialogStack.isEmpty()) { + int last = dialogStack.size() - 1; + String id = dialogStack.get(last); + iitc_view.loadUrl("javascript: " + + "var selector = $(window.DIALOGS['" + id + "']); " + + "selector.dialog('close'); " + + "selector.remove();"); + return; + } + // exit fullscreen mode if it is enabled and action bar is disabled + // or the back stack is empty if (fullscreen_mode && (backStack.isEmpty() || fullscreen_actionbar)) { this.toggleFullscreen(); } else if (!backStack.isEmpty()) { // Pop last item from backStack and pretend the relevant menu item was clicked backStackPop(); } else { - super.onBackPressed(); + if (back_button_pressed || !sharedPref.getBoolean("pref_press_twice_to_exit", false)) + super.onBackPressed(); + else { + back_button_pressed = true; + Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show(); + // reset back button after 2 seconds + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + back_button_pressed = false; + } + }, 2000); + } } } @@ -293,20 +322,31 @@ public class IITC_Mobile extends Activity { } int index = backStack.size() - 1; int itemId = backStack.remove(index); - currentPane = itemId; - handleMenuItemSelected(itemId, false); - // if we popped our last item from stack...illustrate it on home button - if (backStack.isEmpty()) { - // Empty back stack means we should be at home (ie map) screen - setActionBarHomeEnabledWithUp(false); - } + backStack_push = false; + handleMenuItemSelected(itemId); } public void backStackUpdate(int itemId) { + // ensure no double adds if (itemId == currentPane) return; - backStack.add(currentPane); + if (itemId == android.R.id.home) { + backStack.clear(); + backStack_push = true; + } else { + if (backStack_push) + backStack.add(currentPane); + else + backStack_push = true; + } + currentPane = itemId; - if (backStack.size() == 1) setActionBarHomeEnabledWithUp(true); + if (backStack.size() >= 1) { + setActionBarHomeEnabledWithUp(true); + } else { + // if we popped our last item from stack...illustrate it on home button + // Empty back stack means we should be at home (ie map) screen + setActionBarHomeEnabledWithUp(false); + } } @Override @@ -330,24 +370,21 @@ public class IITC_Mobile extends Activity { public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection final int itemId = item.getItemId(); - boolean result = handleMenuItemSelected(itemId, true); - if (!result) return super.onOptionsItemSelected(item); - return true; + boolean result = handleMenuItemSelected(itemId); + return result || super.onOptionsItemSelected(item); } - public boolean handleMenuItemSelected(int itemId, boolean addToBackStack) { + public boolean handleMenuItemSelected(int itemId) { switch (itemId) { case android.R.id.home: iitc_view.loadUrl("javascript: window.show('map');"); - actionBar.setTitle(getString(R.string.app_name)); - this.backStack.clear(); - setActionBarHomeEnabledWithUp(false); - currentPane = android.R.id.home; return true; case R.id.reload_button: actionBar.setTitle(getString(R.string.app_name)); backStack.clear(); setActionBarHomeEnabledWithUp(false); + // iitc starts on map after reload + currentPane = android.R.id.home; this.loadUrl(intel_url); return true; case R.id.toggle_fullscreen: @@ -359,15 +396,21 @@ public class IITC_Mobile extends Activity { iitc_view.loadUrl("javascript: window.show('map');"); // the getLayers function calls the setLayers method of IITC_JSInterface iitc_view.loadUrl("javascript: window.layerChooser.getLayers()"); - actionBar.setTitle(getString(R.string.app_name)); - backStackUpdate(android.R.id.home); return true; // get the users current location and focus it on map case R.id.locate: iitc_view.loadUrl("javascript: window.show('map');"); - iitc_view.loadUrl("javascript: window.map.locate({setView : true, maxZoom: 15});"); - actionBar.setTitle(getString(R.string.app_name)); - backStackUpdate(android.R.id.home); + // get location from network by default + if (!is_loc_enabled) { + iitc_view.loadUrl("javascript: " + + "window.map.locate({setView : true, maxZoom: 15});"); + // if gps location is displayed we can use a better location without any costs + } else { + if (last_location != null) + iitc_view.loadUrl("javascript: window.map.setView(new L.LatLng(" + + last_location.getLatitude() + "," + + last_location.getLongitude() + "), 15);"); + } return true; // start settings activity case R.id.action_settings: @@ -378,33 +421,21 @@ public class IITC_Mobile extends Activity { return true; case R.id.menu_info: iitc_view.loadUrl("javascript: window.show('info');"); - actionBar.setTitle(getString(R.string.menu_info)); - if (addToBackStack) backStackUpdate(itemId); return true; case R.id.menu_full: iitc_view.loadUrl("javascript: window.show('full');"); - actionBar.setTitle(getString(R.string.menu_full)); - if (addToBackStack) backStackUpdate(itemId); return true; case R.id.menu_compact: iitc_view.loadUrl("javascript: window.show('compact');"); - actionBar.setTitle(getString(R.string.menu_compact)); - if (addToBackStack) backStackUpdate(itemId); return true; case R.id.menu_public: iitc_view.loadUrl("javascript: window.show('public');"); - actionBar.setTitle(getString(R.string.menu_public)); - if (addToBackStack) backStackUpdate(itemId); return true; case R.id.menu_faction: iitc_view.loadUrl("javascript: window.show('faction');"); - actionBar.setTitle(getString(R.string.menu_faction)); - if (addToBackStack) backStackUpdate(itemId); return true; case R.id.menu_debug: iitc_view.loadUrl("javascript: window.show('debug')"); - actionBar.setTitle(getString(R.string.menu_debug)); - if (addToBackStack) backStackUpdate(itemId); return true; default: return false; @@ -475,8 +506,8 @@ public class IITC_Mobile extends Activity { } /** - * It can occur that in order to authenticate, an external activity has to be launched. (This could for example be a - * confirmation dialog.) + * It can occur that in order to authenticate, an external activity has to be launched. + * (This could for example be a confirmation dialog.) */ public void startLoginActivity(Intent launch) { startActivityForResult(launch, REQUEST_LOGIN); // REQUEST_LOGIN is to recognize the result @@ -500,6 +531,8 @@ public class IITC_Mobile extends Activity { */ public void onReceivedLoginRequest(IITC_WebViewClient client, WebView view, String realm, String account, String args) { + Log.d("iitcm", "logging in...set caching mode to default"); + iitc_view.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); mLogin = new IITC_DeviceAccountLogin(this, view, client); mLogin.startLogin(realm, account, args); } @@ -522,4 +555,24 @@ public class IITC_Mobile extends Activity { item = menu.findItem(R.id.menu_debug); item.setVisible(!desktop); } + + // remove dialog and add it back again + // to ensure it is the last element of the list + // focused dialogs should be closed first + public void setFocusedDialog(String id) { + Log.d("iitcm", "Dialog " + id + " focused"); + dialogStack.remove(id); + dialogStack.add(id); + } + + // called by the javascript interface + public void dialogOpened(String id, boolean open) { + if (open) { + Log.d("iitcm", "Dialog " + id + " added"); + dialogStack.add(id); + } else { + Log.d("iitcm", "Dialog " + id + " closed"); + dialogStack.remove(id); + } + } } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreference.java b/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreference.java new file mode 100644 index 00000000..32d6541b --- /dev/null +++ b/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreference.java @@ -0,0 +1,34 @@ +package com.cradle.iitc_mobile; + +import android.content.Context; +import android.preference.CheckBoxPreference; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +// multiline checkbox preference +public class IITC_PluginPreference extends CheckBoxPreference { + + public IITC_PluginPreference(Context context) { + super(context); + } + + protected void onBindView(View view) { + super.onBindView(view); + makeMultiline(view); + } + + protected void makeMultiline(View view) { + if (view instanceof ViewGroup) { + ViewGroup grp = (ViewGroup) view; + for (int index = 0; index < grp.getChildCount(); index++) { + makeMultiline(grp.getChildAt(index)); + } + } else if (view instanceof TextView) { + TextView t = (TextView) view; + t.setSingleLine(false); + t.setEllipsize(null); + } + } + +} diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java b/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java index fa59966a..4ac7efe6 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Settings.java @@ -1,16 +1,7 @@ package com.cradle.iitc_mobile; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Scanner; - import android.app.Activity; -import android.content.res.AssetManager; import android.os.Bundle; -import android.os.Environment; -import android.util.Log; import android.view.MenuItem; public class IITC_Settings extends Activity { @@ -21,70 +12,12 @@ public class IITC_Settings extends Activity { IITC_SettingsFragment settings = new IITC_SettingsFragment(); - AssetManager am = this.getAssets(); - String[] asset_array = null; - try { - asset_array = am.list("plugins"); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - // set action bar title - this.getActionBar().setTitle("IITC Mobile Settings"); - this.getActionBar().setHomeButtonEnabled(true); - - ArrayList asset_list = new ArrayList(); - ArrayList asset_values = new ArrayList(); - - for (int i = 0; i < asset_array.length; i++) { - // find user plugin name for user readable entries - Scanner s = null; - String src = ""; - try { - s = new Scanner(am.open("plugins/" + asset_array[i])) - .useDelimiter("\\A"); - } catch (IOException e2) { - // TODO Auto-generated catch block - e2.printStackTrace(); - } - if (s != null) - src = s.hasNext() ? s.next() : ""; - String plugin_name = getPluginName(src); - asset_list.add(plugin_name); - // real value - asset_values.add(asset_array[i]); - } - - // load additional plugins from /IITC_Mobile/plugins/ - String iitc_path = Environment.getExternalStorageDirectory().getPath() - + "/IITC_Mobile/"; - File directory = new File(iitc_path + "plugins/"); - File[] files = directory.listFiles(); - if (files != null) { - Scanner s = null; - String src = ""; - for (int i = 0; i < files.length; ++i) { - try { - s = new Scanner(files[i]).useDelimiter("\\A"); - } catch (FileNotFoundException e) { - e.printStackTrace(); - Log.d("iitcm", "failed to parse file " + files[i]); - } - if (s != null) - src = s.hasNext() ? s.next() : ""; - String plugin_name = getPluginName(src); - asset_list.add("[User] " + plugin_name); - // real value - asset_values.add(files[i].toString()); - } - } + getActionBar().setTitle("IITC Mobile Settings"); + getActionBar().setHomeButtonEnabled(true); + // iitc version Bundle bundle = getIntent().getExtras(); - bundle.putStringArray("ASSETS", - (String[]) asset_list.toArray(new String[0])); - bundle.putStringArray("ASSETS_VAL", - (String[]) asset_values.toArray(new String[0])); settings.setArguments(bundle); // Display the fragment as the main content. @@ -92,30 +25,12 @@ public class IITC_Settings extends Activity { .replace(android.R.id.content, settings).commit(); } - // parse header for @name of plugin - public String getPluginName(String src) { - String header = src.substring(src.indexOf("==UserScript=="), - src.indexOf("==/UserScript==")); - // remove new line comments and replace with space - // this way we get double spaces instead of newline + double slash - header = header.replace("\n//", " "); - // get a list of key-value...split on multiple spaces - String[] attributes = header.split(" +"); - String plugin_name = "not found"; - for (int j = 0; j < attributes.length; j++) { - // search for name and use the value - if (attributes[j].equals("@name")) - plugin_name = attributes[j + 1]; - } - return plugin_name; - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // exit settings when home button (iitc icon) is pressed - case android.R.id.home : - this.finish(); + case android.R.id.home: + onBackPressed(); return true; default: return super.onOptionsItemSelected(item); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java b/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java index 3859a5f4..f5fab725 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_SettingsFragment.java @@ -3,17 +3,25 @@ package com.cradle.iitc_mobile; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.AssetManager; import android.os.Bundle; +import android.os.Environment; import android.preference.EditTextPreference; import android.preference.ListPreference; -import android.preference.MultiSelectListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; +import android.util.Log; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Scanner; public class IITC_SettingsFragment extends PreferenceFragment { - String iitc_version; + private String iitc_version; @Override public void onCreate(Bundle savedInstanceState) { @@ -24,10 +32,7 @@ public class IITC_SettingsFragment extends PreferenceFragment { addPreferencesFromResource(R.xml.preferences); // plugins - MultiSelectListPreference pref_plugins = (MultiSelectListPreference) findPreference("pref_plugins"); - pref_plugins.setEntries(getArguments().getStringArray("ASSETS")); - pref_plugins - .setEntryValues(getArguments().getStringArray("ASSETS_VAL")); + setUpPluginPreferenceScreen(); // set build version ListPreference pref_build_version = (ListPreference) findPreference("pref_build_version"); @@ -52,16 +57,131 @@ public class IITC_SettingsFragment extends PreferenceFragment { .setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, - Object newValue) { - preference.setSummary((CharSequence) newValue); + Object newValue) { + preference.setSummary(getString(R.string.pref_select_iitc_sum) + + " " + newValue); // TODO: update iitc_version when iitc source has // changed return true; } }); // first init of summary - String pref_iitc_source_sum = (String) pref_iitc_source.getSummary() - + pref_iitc_source.getText(); + String pref_iitc_source_sum = getString(R.string.pref_select_iitc_sum) + + " " + pref_iitc_source.getText(); pref_iitc_source.setSummary(pref_iitc_source_sum); } + + void setUpPluginPreferenceScreen() { + PreferenceScreen root = (PreferenceScreen) findPreference("pref_plugins"); + // alphabetical order + root.setOrderingAsAdded(false); + root.setPersistent(true); + + // get all plugins from asset manager + AssetManager am = this.getActivity().getAssets(); + String[] asset_array = null; + try { + asset_array = am.list("plugins"); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + for (String anAsset_array : asset_array) { + // find user plugin name for user readable entries + Scanner s = null; + String src = ""; + try { + s = new Scanner(am.open("plugins/" + anAsset_array)) + .useDelimiter("\\A"); + } catch (IOException e2) { + // TODO Auto-generated catch block + e2.printStackTrace(); + } + if (s != null) + src = s.hasNext() ? s.next() : ""; + // now we have all stuff together and can build the pref screen + addPluginPreference(root, src, anAsset_array, false); + } + + // load additional plugins from /IITC_Mobile/plugins/ + String iitc_path = Environment.getExternalStorageDirectory().getPath() + + "/IITC_Mobile/"; + File directory = new File(iitc_path + "plugins/"); + File[] files = directory.listFiles(); + if (files != null) { + Scanner s = null; + String src = ""; + for (File file : files) { + try { + s = new Scanner(file).useDelimiter("\\A"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + Log.d("iitcm", "failed to parse file " + file); + } + if (s != null) + src = s.hasNext() ? s.next() : ""; + + // now we have all stuff together and can build the pref screen + addPluginPreference(root, src, file.toString(), true); + } + } + } + + void addPluginPreference(PreferenceScreen root, String src, String plugin_key, + boolean additional) { + + // 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]; + } + + // remove IITC plugin prefix from plugin_name + plugin_name = plugin_name.replace("IITC Plugin: ", ""); + plugin_name = plugin_name.replace("IITC plugin: ", ""); + + // add [User] tag to additional plugins + if (additional) + plugin_cat = "[User] " + plugin_cat; + // now we have all stuff together and can build the pref screen + PreferenceScreen pref_screen; + if (root.findPreference(plugin_cat) == null) { + Log.d("iitcm", "create " + plugin_cat + " and add " + plugin_name); + pref_screen = getPreferenceManager().createPreferenceScreen(root.getContext()); + pref_screen.setTitle(plugin_cat); + pref_screen.setKey(plugin_cat); + // alphabetical order + pref_screen.setOrderingAsAdded(false); + pref_screen.setPersistent(true); + root.addPreference(pref_screen); + } else { + Log.d("iitcm", "add " + plugin_name + " to " + plugin_cat); + pref_screen = (PreferenceScreen) findPreference(plugin_cat); + } + + // now build a new checkable preference for the plugin + IITC_PluginPreference plugin_pref = new IITC_PluginPreference(pref_screen.getContext()); + plugin_pref.setKey(plugin_key); + plugin_pref.setTitle(plugin_name); + plugin_pref.setSummary(plugin_desc); + plugin_pref.setDefaultValue(false); + plugin_pref.setPersistent(true); + pref_screen.addPreference(plugin_pref); + } } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java index 2a910f2a..7522ce1d 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java @@ -11,10 +11,10 @@ import android.os.Build; import android.preference.PreferenceManager; import android.util.AttributeSet; import android.util.Log; +import android.webkit.GeolocationPermissions; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; -import android.webkit.GeolocationPermissions; @SuppressLint("SetJavaScriptEnabled") public class IITC_WebView extends WebView { @@ -26,7 +26,7 @@ public class IITC_WebView extends WebView { // init web view private void iitc_init(Context c) { - if ( this.isInEditMode() ) return; + if (this.isInEditMode()) return; settings = this.getSettings(); settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); @@ -37,19 +37,18 @@ public class IITC_WebView extends WebView { + "/databases/"); settings.setAppCachePath(this.getContext().getCacheDir() .getAbsolutePath()); - // use cache if on mobile network...saves traffic this.js_interface = new IITC_JSInterface(c); this.addJavascriptInterface(js_interface, "android"); this.setWebChromeClient(new WebChromeClient() { /** * our webchromeclient should share geolocation with the iitc script - * + * * allow access by default */ @Override public void onGeolocationPermissionsShowPrompt(String origin, - GeolocationPermissions.Callback callback) { + GeolocationPermissions.Callback callback) { callback.invoke(origin, true, false); } @@ -95,8 +94,8 @@ public class IITC_WebView extends WebView { public void loadUrl(String url) { // if in edit text mode, don't load javascript otherwise the keyboard closes. HitTestResult testResult = this.getHitTestResult(); - if (url.startsWith("javascript:") && testResult != null && testResult.getType() == HitTestResult.EDIT_TEXT_TYPE) - { + if (url.startsWith("javascript:") && testResult != null && + testResult.getType() == HitTestResult.EDIT_TEXT_TYPE) { // let window.show(...) interupt input // window.show(...) is called if one of the action bar buttons // is clicked @@ -106,7 +105,7 @@ public class IITC_WebView extends WebView { } } // do nothing if script is enabled; - if (this.disableJS == true) { + if (this.disableJS) { Log.d("iitcm", "javascript injection disabled...return"); return; } @@ -132,6 +131,7 @@ public class IITC_WebView extends WebView { } public void updateCaching() { + // use cache if on mobile network...saves traffic if (!this.isConnectedToWifi()) { Log.d("iitcm", "not connected to wifi...load tiles from cache"); settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); @@ -152,7 +152,8 @@ public class IITC_WebView extends WebView { // is ticked as mobile hotspot or not. // --> IITC_WebView.isConnectedToWifi should return 'false' if connected to mobile hotspot if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - return ((wifi.getState() == NetworkInfo.State.CONNECTED) && !conMan.isActiveNetworkMetered()); + return ((wifi.getState() == NetworkInfo.State.CONNECTED) && + !conMan.isActiveNetworkMetered()); } return (wifi.getState() == NetworkInfo.State.CONNECTED); } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index 4333a8ad..4fb66594 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -12,17 +12,23 @@ 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 java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; +import java.util.Map; import java.util.Scanner; -import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public class IITC_WebViewClient extends WebViewClient { private static final ByteArrayInputStream style = new ByteArrayInputStream( @@ -34,7 +40,7 @@ public class IITC_WebViewClient extends WebViewClient { private WebResourceResponse iitcjs; private String js = null; private String iitc_path = null; - Context context; + private final Context context; public IITC_WebViewClient(Context c) { this.context = c; @@ -76,7 +82,7 @@ public class IITC_WebViewClient extends WebViewClient { js = this.fileToString(iitc_path + "dev/total-conversion-build.user.js", false); if (js.equals("false")) { - Toast.makeText( context, "File " + iitc_path + + Toast.makeText(context, "File " + iitc_path + "dev/total-conversion-build.user.js not found. " + "Disable developer mode or add iitc files to the dev folder.", Toast.LENGTH_LONG).show(); @@ -89,8 +95,19 @@ public class IITC_WebViewClient extends WebViewClient { // load iitc script from web or asset folder if (iitc_source.contains("http")) { URL url = new URL(iitc_source); - js = new Scanner(url.openStream(), "UTF-8").useDelimiter("\\A") - .next(); + // if parsing of the online iitc source timed out, use the script from assets + try { + js = new UrlContentToString().execute(url).get(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + js = this.fileToString("total-conversion-build.user.js", true); + } catch (ExecutionException e) { + e.printStackTrace(); + js = this.fileToString("total-conversion-build.user.js", true); + } catch (TimeoutException e) { + e.printStackTrace(); + js = this.fileToString("total-conversion-build.user.js", true); + } } else { js = this.fileToString("total-conversion-build.user.js", true); } @@ -125,20 +142,21 @@ public class IITC_WebViewClient extends WebViewClient { iitcjs = new WebResourceResponse("text/javascript", "UTF-8", new ByteArrayInputStream(js.getBytes())); - }; + } // enable https @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, - SslError error) { + SslError error) { handler.proceed(); - }; + } /** * this method is called automatically when the Google login form is opened. */ @Override public void onReceivedLoginRequest(WebView view, String realm, String account, String args) { + Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args); ((IITC_Mobile) context).onReceivedLoginRequest(this, view, realm, account, args); } @@ -149,26 +167,26 @@ public class IITC_WebViewClient extends WebViewClient { // get the plugin preferences SharedPreferences sharedPref = PreferenceManager .getDefaultSharedPreferences(context); - Set plugin_list = sharedPref.getStringSet("pref_plugins", null); boolean dev_enabled = sharedPref.getBoolean("pref_dev_checkbox", false); - // iterate through all enabled plugins and load them - if (plugin_list != null) { - String[] plugin_array = plugin_list.toArray(new String[0]); + Map all_prefs = sharedPref.getAll(); - for (int i = 0; i < plugin_list.size(); i++) { + // iterate through all plugins + for (Map.Entry entry : all_prefs.entrySet()) { + String plugin = entry.getKey(); + if (plugin.endsWith("user.js") && entry.getValue().toString().equals("true")) { // load default iitc plugins - if (!plugin_array[i].startsWith(iitc_path)) { - Log.d("iitcm", "adding plugin " + plugin_array[i]); + if (!plugin.startsWith(iitc_path)) { + Log.d("iitcm", "adding plugin " + plugin); if (dev_enabled) js += this.removePluginWrapper(iitc_path + "dev/plugins/" - + plugin_array[i], false); + + plugin, false); else - js += this.removePluginWrapper("plugins/" + plugin_array[i], true); - // load additional iitc plugins + js += this.removePluginWrapper("plugins/" + plugin, true); + // load additional iitc plugins } else { - Log.d("iitcm", "adding additional plugin " + plugin_array[i]); - js += this.removePluginWrapper(plugin_array[i], false); + Log.d("iitcm", "adding additional plugin " + plugin); + js += this.removePluginWrapper(plugin, false); } } } @@ -244,30 +262,28 @@ public class IITC_WebViewClient extends WebViewClient { public String removePluginWrapper(String file, boolean asset) { if (!file.endsWith("user.js")) return ""; String js = fileToString(file, asset); - if (js == "false") return ""; + 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);"; + "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("function wrapper() {", ""); + js = js.replace(wrapper_start, ""); // remove the wrapper function - js = js.replace("} // wrapper end", ""); + js = js.replace(wrapper_end, ""); // and the code injection - js = js.replace("// 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);", ""); + js = js.replace(injection_code, ""); } else { Log.d("iitcm", "Removal of wrapper/injection code failed for " + file); return ""; } return js; } + // Check every external resource if it’s okay to load it and maybe replace // it // with our own content. This is used to block loading Niantic resources @@ -275,7 +291,7 @@ public class IITC_WebViewClient extends WebViewClient { // via http://stackoverflow.com/a/8274881/1684530 @Override public WebResourceResponse shouldInterceptRequest(final WebView view, - String url) { + String url) { if (url.contains("/css/common.css")) { return new WebResourceResponse("text/css", "UTF-8", style); } else if (url.contains("gen_dashboard.js")) { @@ -308,6 +324,10 @@ public class IITC_WebViewClient extends WebViewClient { + url); ((IITC_Mobile) context).loadUrl(url); } + if (url.contains("logout")) { + Log.d("iitcm", "logging out...set caching mode to default"); + view.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); + } return false; } else { Log.d("iitcm", diff --git a/mobile/src/com/cradle/iitc_mobile/async/UrlContentToString.java b/mobile/src/com/cradle/iitc_mobile/async/UrlContentToString.java new file mode 100644 index 00000000..4feb40e5 --- /dev/null +++ b/mobile/src/com/cradle/iitc_mobile/async/UrlContentToString.java @@ -0,0 +1,31 @@ +package com.cradle.iitc_mobile.async; + +import android.os.AsyncTask; + +import com.cradle.iitc_mobile.IITC_Mobile; + +import java.io.IOException; +import java.net.URL; +import java.util.Scanner; + +/* + * this class parses the content of a web page. + * since network operations shouldn't be done on main UI thread + * (NetworkOnMainThread exception is thrown) we use an async task for this. + */ +public class UrlContentToString extends AsyncTask { + + @Override + protected String doInBackground(URL... urls) { + String js = ""; + URL url = urls[0]; + try { + js = new Scanner(url.openStream(), "UTF-8").useDelimiter("\\A") + .next(); + } catch (IOException e) { + e.printStackTrace(); + } + return js; + } + +} diff --git a/plugins/ap-list.user.js b/plugins/ap-list.user.js index 7a1088c5..a51bff27 100644 --- a/plugins/ap-list.user.js +++ b/plugins/ap-list.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-ap-list@xelio // @name IITC plugin: AP List +// @category Info // @version 0.5.3.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -947,16 +945,4 @@ var setup = function() { } // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/basemap-blank.user.js b/plugins/basemap-blank.user.js index 955e601a..9cb7dbd5 100644 --- a/plugins/basemap-blank.user.js +++ b/plugins/basemap-blank.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-basemap-blank@jonatkins // @name IITC plugin: Blank map +// @category Map Tiles // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -36,16 +34,4 @@ var setup = window.plugin.mapTileBlank.addLayer; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/basemap-cloudmade.user.js b/plugins/basemap-cloudmade.user.js index b6857696..dbfb0144 100644 --- a/plugins/basemap-cloudmade.user.js +++ b/plugins/basemap-cloudmade.user.js @@ -24,6 +24,7 @@ // ==UserScript== // @id iitc-plugin-cloudmade-maps // @name IITC plugin: CloudMade.com maps +// @category Map Tiles // @version 0.0.1 // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @description TEMPLATE PLUGIN - add back the CloudMade.com map layers. YOU WILL NEED TO EDIT THIS PLUGIN BEFORE IT WILL RUN @@ -33,10 +34,7 @@ // @match http://www.ingress.com/intel* // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -87,16 +85,4 @@ var setup = window.plugin.mapTileCloudMade.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/basemap-opencyclemap.user.js b/plugins/basemap-opencyclemap.user.js index a024ec00..5d5964e0 100644 --- a/plugins/basemap-opencyclemap.user.js +++ b/plugins/basemap-opencyclemap.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-basemap-opencyclepam@jonatkins // @name IITC plugin: OpenCycleMap.org map tiles +// @category Map Tiles // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -43,16 +41,4 @@ var setup = window.plugin.mapTileOpenCycleMap.addLayer; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/basemap-openstreetmap.user.js b/plugins/basemap-openstreetmap.user.js index 57122fb8..3a1ebc59 100644 --- a/plugins/basemap-openstreetmap.user.js +++ b/plugins/basemap-openstreetmap.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-basemap-openstreetpam@jonatkins // @name IITC plugin: OpenStreetMap.org map tiles +// @category Map Tiles // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -40,16 +38,4 @@ var setup = window.plugin.mapTileOpenStreetMap.addLayer; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/basemap-yandex.user.js b/plugins/basemap-yandex.user.js index b4cbcc6f..5e65092e 100644 --- a/plugins/basemap-yandex.user.js +++ b/plugins/basemap-yandex.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-basemap-yandex@jonatkins // @name IITC plugin: Yandex maps +// @category Map Tiles // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -61,16 +59,4 @@ var setup = window.plugin.mapTileYandex.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/bookmarks-by-zaso-css-desktop.css b/plugins/bookmarks-by-zaso-css-desktop.css new file mode 100644 index 00000000..a738ffc1 --- /dev/null +++ b/plugins/bookmarks-by-zaso-css-desktop.css @@ -0,0 +1,324 @@ +#bookmarksBox *{ + display:block; + padding:0; + margin:0; + width:auto; + height:auto; + font-family:Verdana, Geneva, sans-serif; + font-size:13px; + line-height:22px; + text-indent:0; + text-decoration:none; +} +#bookmarksBox{ + margin-top:-200%; + position:absolute !important; + z-index:4001; + top:100px; + left:100px; +} +#bookmarksBox .addForm, #bookmarksBox #bookmarksTypeBar, #bookmarksBox h5{ + height:28px; + overflow:hidden; + color:#fff; + font-size:14px; +} +#bookmarksBox #topBar, #bookmarksBox #topBar *{ + height:15px !important; +} +#bookmarksBox #topBar *{ + float:left !important; +} +#bookmarksBox .handle{ + text-indent:-20px; + width:209px; + text-align:center; + color:#fff; + line-height:8px; + cursor:move; +} +#bookmarksBox #topBar .btn{ + display:block; + width:19px; + cursor:pointer; + color:#20a8b1; +} +#bookmarksBox #topBar #bookmarksMin{ + font-weight:bold; + text-align:center; + line-height:14px; + font-size:18px; +} +#bookmarksBox #topBar #bookmarksMin:hover{ + color:gold; +} +#bookmarksBox #bookmarksTypeBar{ + clear:both; +} +#bookmarksBox h5{ + padding:4px 0; + width:114px; + text-align:center; + color:#788; +} +#bookmarksBox h5.current{ + cursor:default; + background:0; + color:#fff !important; +} +#bookmarksBox h5:hover{ + color:gold; + background:rgba(0,0,0,0); +} +#bookmarksBox #topBar .btn, #bookmarksBox .addForm, #bookmarksBox .handle, #bookmarksBox #bookmarksTypeBar, #bookmarksBox .bookmarkList li.bookmarksEmpty, #bookmarksBox .bookmarkList li.bkmrk a, #bookmarksBox .bookmarkList li.bkmrk:hover{ + background-color:rgba(8,48,78,.85); +} +#bookmarksBox h5, #bookmarksBox .bookmarkList li.bkmrk:hover .bookmarksLink, #bookmarksBox .addForm *{ + background:rgba(0,0,0,.3); +} +#bookmarksBox .addForm *{ + display:block; + float:left; + padding:4px 8px 3px; +} +#bookmarksBox .addForm a{ + cursor:pointer; + color:#20a8b1; + font-size:12px; + width:65px; + text-align:center; + line-height:20px; + padding:4px 0 3px; +} +#bookmarksBox .addForm a:hover{ + background:gold; + color:#000; + text-decoration:none; +} +#bookmarksBox .addForm input{ + font-size:11px !important; + color:#ffce00; + width:81px; + line-height:11px; + font-size:12px; + -webkit-box-sizing:content-box; + -moz-box-sizing:content-box; + box-sizing:content-box; +} +#bookmarksBox #bkmrk_portals .addForm input{ + width:147px; +} +#bookmarksBox .addForm input:hover, #bookmarksBox .addForm input:focus{ + outline:0; + background:rgba(0,0,0,.6); +} +#bookmarksBox .bookmarkList>ul{ + width:231px; + clear:both; + list-style-type:none; + color:#fff; + overflow:hidden; + max-height:550px; +} +#bookmarksBox .sortable-placeholder{ + background:rgba(8,48,78,.55); + box-shadow:inset 1px 0 0 #20a8b1; +} +#bookmarksBox .ui-sortable-helper{ + border-top-width:1px; +} +#bookmarksBox .bookmarkList{ + display:none; +} +#bookmarksBox .bookmarkList.current{ + display:block; +} +#bookmarksBox h5, #bookmarksBox .addForm *, #bookmarksBox ul li.bkmrk, #bookmarksBox ul li.bkmrk a{ + height:22px; +} +#bookmarksBox h5, #bookmarksBox ul li.bkmrk a{ + overflow:hidden; + cursor:pointer; + float:left; +} +#bookmarksBox ul .bookmarksEmpty{ + text-indent:27px; + color:#eee; +} +#bookmarksBox ul .bookmarksRemoveFrom{ + width:19px; + text-align:center; + color:#fff; +} +#bookmarksBox ul .bookmarksLink{ + width:171px; + padding:0 10px 0 8px; + color:gold; +} +#bookmarksBox ul .bookmarksLink.selected{ + color:#03fe03; +} +#bookmarksBox ul .othersBookmarks .bookmarksLink{ + width:190px; +} +#bookmarksBox ul .bookmarksLink:hover{ + color:#03fe03; +} +#bookmarksBox ul .bookmarksRemoveFrom:hover{ + color:#fff; + background:#e22; +} +#bookmarksBox, #bookmarksBox *{ + border-color:#20a8b1; + border-style:solid; + border-width:0; +} +#bookmarksBox #topBar, #bookmarksBox ul .bookmarkFolder{ + border-top-width:1px; +} +#bookmarksBox #topBar, #bookmarksBox #bookmarksTypeBar, #bookmarksBox .addForm, #bookmarksBox ul .bookmarkFolder .folderLabel, #bookmarksBox ul li.bkmrk{ + border-bottom-width:1px; +} +#bookmarksBox ul .bookmarkFolder, #bookmarksBox ul .bookmarksRemoveFrom{ + border-right-width:1px; + border-left-width:1px; +} +#bookmarksBox #topBar *, #bookmarksBox #bookmarksTypeBar *, #bookmarksBox .addForm *{ + border-left-width:1px; +} +#bookmarksBox #topBar, #bookmarksBox #bookmarksTypeBar, #bookmarksBox .addForm{ + border-right-width:1px; +} +#bookmarksBox ul .othersBookmarks .bookmarksRemoveFrom, #bookmarksBox ul .bookmarkFolder .folderLabel .bookmarksRemoveFrom{ + border-left-width:0; +} +#bookmarksShow{ + display:block; + position:absolute; + top:0; + left:250px; + width:47px; + margin-top:-36px; + height:64px; + cursor:pointer; + z-index:2999; + background-position:center bottom; + background-repeat:no-repeat; + transition:margin-top 100ms ease-in-out; + background-image:url(@@INCLUDEIMAGE:plugins/bookmarks-by-zaso-logo.png@@); +} +#bookmarksShow:hover{ + margin-top:0 !important; +} +#sidebar #portaldetails h3.title{ + width:auto; +} +#bookmarkStar{ + display:inline-block; + float:left; + margin:3px 1px 0 4px; + width:16px; + height:15px; + overflow:hidden; + background-image:url(@@INCLUDEIMAGE:plugins/bookmarks-by-zaso-star.png@@); + background-position:left center; + background-repeat:no-repeat; +} +#bookmarkStar:hover, #bookmarkStar.favorite{ + background-position:right center; +} +#bookmarksBox .handleScroll{ + cursor:s-resize; + width:3px; + right:3px; + background:gold; + opacity:.7; +} +#bookmarksBox .bookmarkList .bookmarkFolder{ + overflow:hidden; + margin-top:-1px; + height:auto; + background:rgba(8,58,78,.7); +} +#bookmarksBox .bookmarkList ul li.sortable-placeholder{ + box-shadow:inset -1px 0 0 #20a8b1, inset 1px 0 0 #20a8b1, 0 -1px 0 #20a8b1; + background:rgba(8,58,78,.9); +} +#bookmarksBox .bookmarkList .bkmrk.ui-sortable-helper{ + border-right-width:1px; + border-left-width:1px; +} +#bookmarksBox .bookmarkList ul li ul li.sortable-placeholder{ + height:23px; + box-shadow:inset 0 -1px 0 #20a8b1, inset 1px 0 0 #20a8b1; +} +#bookmarksBox .bookmarkList ul li.bookmarkFolder.ui-sortable-helper, #bookmarksBox .bookmarkList ul li.othersBookmarks ul, #bookmarksBox .bookmarkList ul li.othersBookmarks ul li.sortable-placeholder{ + box-shadow:inset 0 -1px 0 #20a8b1; +} +#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span, #bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span, #bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span, #bookmarksBox .bookmarkList .triangle{ + width:0; + height:0; +} +#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel{ + overflow:visible; + height:25px; + cursor:pointer; + background:#069; + text-indent:0; +} +#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>*{ + height:25px; + float:left; +} +#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor{ + line-height:25px; + color:#fff; + width:209px; +} +#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span{ + float:left; + border-width:5px 0 5px 7px; + border-color:transparent transparent transparent white; + margin:7px 7px 0 6px; +} +#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel .bookmarksAnchor span{ + margin:9px 5px 0 5px; + border-width:7px 5px 0 5px; + border-color:white transparent transparent transparent; +} +#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span, #bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span{ + display:none; + border-width:0 12px 10px 0; + border-color:transparent #20a8b1 transparent transparent; + margin:-20px 0 0; + position:relative; + top:21px; + left:219px; +} +#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span{ + top:18px; + left:0; + border-width:0 10px 9px 0; + border-color:transparent #069 transparent transparent; +} +#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel>span, #bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel>span>span{ + display:block; +} +#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel:hover>span>span{ + border-color:transparent #036 transparent transparent; +} +#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel:hover .bookmarksAnchor{ + background:#036; +} +#bookmarksBox .bookmarkList .bookmarkFolder ul{ + display:none; + margin-left:19px; +} +#bookmarksBox .bookmarkList .bookmarkFolder.active ul{ + display:block; + min-height:22px; +} +#bookmarksBox .bookmarkFolder.othersBookmarks ul{ + margin-left:0; +} +) diff --git a/plugins/bookmarks-by-zaso-css-mobile.css b/plugins/bookmarks-by-zaso-css-mobile.css new file mode 100644 index 00000000..ac2e79f4 --- /dev/null +++ b/plugins/bookmarks-by-zaso-css-mobile.css @@ -0,0 +1,136 @@ +#sidebar #bookmarksBox{ + position:static !important; + width:auto !important; + margin:0 !important; + width:100%; +} +#sidebar #bookmarksBox .bookmarkList > ul > li, #sidebar #bookmarksBox .bookmarkList > ul > li > ul, #sidebar #bookmarksBox .bookmarkList > ul > li > ul > li{ + width:100% !important; +} +#sidebar #bookmarksBox *{ + box-shadow:none !important; + border-width:0 !important +} +#sidebar #bookmarksBox #topBar{ + display:none !important; +} +#sidebar #bookmarksBox #bookmarksTypeBar h5{ + cursor:pointer; + text-align:center; + float:left; + width:50%; + padding:7px 0; +} +#sidebar #bookmarksBox #bookmarksTypeBar h5.current{ + cursor:default; + color:#fff; +} +#sidebar #bookmarksBox #bookmarksTypeBar, #sidebar #bookmarksBox .bookmarkList .addForm{ + border-bottom:1px solid #20a8b1 !important; +} +#sidebar #bookmarksBox .bookmarkList ul li ul li.bkmrk{ + height:36px !important; + clear:both; +} +#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder .folderLabel{ + height:36px; +} +#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder .folderLabel a, #sidebar #bookmarksBox .bookmarkList ul li ul li.bkmrk a{ + background:none; + padding:7px 0; + height:auto; + box-shadow:inset 0 1px 0 #20a8b1 !important; +} +#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder a.bookmarksRemoveFrom, #sidebar #bookmarksBox .bookmarkList li.bkmrk a.bookmarksRemoveFrom{ + box-shadow:inset 0 1px 0 #20a8b1, inset -1px 0 0 #20a8b1 !important; + width:15%; +} +#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder a.bookmarksAnchor, #sidebar #bookmarksBox .bookmarkList li.bkmrk a.bookmarksLink{ + text-indent:10px; + width:85%; + height:21px /*22*/; + overflow:hidden; +} +#sidebar #bookmarksBox .bookmarkList ul li.bookmarkFolder ul{ + margin-left:0 !important; +} +#sidebar #bookmarksBox .bookmarkList ul, #bookmarksBox .bookmarkList ul li, #sidebar #bookmarksBox .bookmarkList ul li ul, #sidebar #bookmarksBox .bookmarkList ul li ul li{ + display:block !important; +} +#sidebar #bookmarksBox .bookmarkList{ + display:none !important; +} +#sidebar #bookmarksBox .bookmarkList > ul{ + border-bottom:1px solid #20a8b1 !important; + border-right:1px solid #20a8b1 !important; +} +#sidebar #bookmarksBox .bookmarkList.current{ + display:block !important; +} +#sidebar #bookmarksBox .bookmarkList .bookmarkFolder.othersBookmarks ul{ + border-top:5px solid #20a8b1 !important; +} +#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder, #sidebar #bookmarksBox .bookmarkList li.bkmrk{ + box-shadow:inset 0 1px 0 #20a8b1, 1px 0 0 #20a8b1, -1px 1px 0 #20a8b1 !important; +} +#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder .bkmrk.sortable-placeholder{ + height:36px !important; +} +#sidebar #bookmarksBox .bookmarkList .sortable-placeholder{ + box-shadow:inset 0 1px 0 #20a8b1 !important; +} +#sidebar #bookmarksBox .ui-sortable .ui-sortable-helper{ + border-top:0; + width:85% !important; +} +#sidebar #bookmarksBox .bookmarkList > ul{ + max-height:none; + width:85% !important; +} +#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder .folderLabel{ + box-shadow:0 1px 0 #20a8b1 !important; +} +#sidebar #bookmarksBox .bookmarkList ul li.bookmarkFolder ul{ + width:85% !important; + margin-left:15% !important; +} +#sidebar #bookmarksBox .bookmarkList ul li.bookmarkFolder.othersBookmarks ul{ + width:100% !important; + margin-left:0% !important; +} +#sidebar #bookmarksShowMobile{ + text-decoration:none; + display:block !important; + padding:11px 0 9px; + text-align:center; +} +#sidebar #portaldetails{ + margin-top:25px; +} +#sidebar #bookmarksBox #bookmarksTypeBar{ + height:auto; +} +#sidebar #bookmarksBox .addForm, #sidebar #bookmarksBox .addForm *{ + height:35px; + padding:0; +} +#sidebar #bookmarksBox .addForm a{ + line-height:37px; +} +#sidebar #bookmarksBox .addForm a{ + width:25% !important; +} +#sidebar #bookmarksBox .addForm input{ + width:50% !important; + text-indent:10px; +} +#sidebar #bookmarksBox #bkmrk_portals .addForm input{ + width:75% !important; +} +#sidebar #bookmarksBox #bookmarksTypeBar h5, #sidebar #bookmarksBox .bookmarkList .addForm a{ + box-shadow:-1px 0 0 #20a8b1 !important; +} +#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder ul{ + display:block !important; + min-height:37px !important; +} \ No newline at end of file diff --git a/plugins/bookmarks-by-zaso.css b/plugins/bookmarks-by-zaso.css deleted file mode 100644 index d15231bd..00000000 --- a/plugins/bookmarks-by-zaso.css +++ /dev/null @@ -1,368 +0,0 @@ -#bookmarksBox * { - display: block; - width: auto; - height: auto; - font-family: Verdana,Geneva,sans-serif; - font-size: 13px; - line-height: 22px; - text-indent: 0; - text-decoration: none; - margin: 0; - padding: 0; -} - -#bookmarksBox { - margin-top: -100%; - position: absolute!important; - z-index: 4001; - top: 100px; - left: 100px; -} - -#bookmarksBox .addForm,#bookmarksBox #bookmarksTypeBar,#bookmarksBox h5 { - height: 28px; - overflow: hidden; - color: #fff; - font-size: 14px; -} - -#bookmarksBox #topBar,#bookmarksBox #topBar * { - height: 15px!important; -} - -#bookmarksBox #topBar * { - float: left!important; -} - -#bookmarksBox .handle { - text-indent: -20px; - width: 209px; - text-align: center; - color: #fff; - line-height: 8px; - cursor: move; -} - -#bookmarksBox #topBar .btn { - display: block; - width: 19px; - cursor: pointer; - color: #20a8b1; -} - -#bookmarksBox #topBar #bookmarksMin { - font-weight: 700; - text-align: center; - line-height: 14px; - font-size: 18px; -} - -#bookmarksBox #topBar #bookmarksMin: hover { - color: #FFD700; -} - -#bookmarksBox #bookmarksTypeBar { - clear: both; -} - -#bookmarksBox h5 { - width: 114px; - text-align: center; - color: #788; - padding: 4px 0; -} - -#bookmarksBox h5.current { - cursor: default; - background: 0; - color: #fff!important; -} - -#bookmarksBox h5: hover { - color: #FFD700; - background: rgba(0,0,0,0); -} - -#bookmarksBox #topBar .btn,#bookmarksBox .addForm,#bookmarksBox .handle,#bookmarksBox #bookmarksTypeBar,#bookmarksBox .bookmarkList li.bookmarksEmpty,#bookmarksBox .bookmarkList li.bkmrk a,#bookmarksBox .bookmarkList li.bkmrk: hover { - background-color: rgba(8,48,78,.85); -} - -#bookmarksBox h5,#bookmarksBox .bookmarkList li.bkmrk: hover .bookmarksLink,#bookmarksBox .addForm * { - background: rgba(0,0,0,.3); -} - -#bookmarksBox .addForm * { - display: block; - float: left; - padding: 4px 8px 3px; -} - -#bookmarksBox .addForm a { - cursor: pointer; - color: #20a8b1; - font-size: 12px; - width: 65px; - text-align: center; - line-height: 20px; - padding: 4px 0 3px; -} - -#bookmarksBox .addForm a: hover { - background: #FFD700; - color: #000; - text-decoration: none; -} - -#bookmarksBox .addForm input { - font-size: 11px!important; - color: #ffce00; - width: 81px; - line-height: 11px; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -#bookmarksBox #bkmrk_portals .addForm input { - width: 147px; -} - -#bookmarksBox .addForm input: hover,#bookmarksBox .addForm input: focus { - outline: 0; - background: rgba(0,0,0,.6); -} - -#bookmarksBox .bookmarkList>ul { - width: 231px; - clear: both; - list-style-type: none; - color: #fff; - overflow: hidden; - max-height: 550px; -} - -#bookmarksBox .sortable-placeholder { - background: rgba(8,48,78,.55); - box-shadow: inset 1px 0 0 #20a8b1; -} - -#bookmarksBox .bookmarkList { - display: none; -} - -#bookmarksBox h5,#bookmarksBox .addForm *,#bookmarksBox ul li.bkmrk,#bookmarksBox ul li.bkmrk a { - height: 22px; -} - -#bookmarksBox h5,#bookmarksBox ul li.bkmrk a { - overflow: hidden; - cursor: pointer; - float: left; -} - -#bookmarksBox ul .bookmarksEmpty { - text-indent: 27px; - color: #eee; -} - -#bookmarksBox ul .bookmarksRemoveFrom { - width: 19px; - text-align: center; - color: #fff; -} - -#bookmarksBox ul .bookmarksLink { - width: 171px; - color: #FFD700; - padding: 0 10px 0 8px; -} - -#bookmarksBox ul .othersBookmarks .bookmarksLink { - width: 190px; -} - -#bookmarksBox ul .bookmarksRemoveFrom: hover { - color: #fff; - background: #e22; -} - -#bookmarksBox,#bookmarksBox * { - border-color: #20a8b1; - border-style: solid; - border-width: 0; -} - -#bookmarksBox #topBar,#bookmarksBox #bookmarksTypeBar,#bookmarksBox .addForm,#bookmarksBox ul .bookmarkFolder .folderLabel,#bookmarksBox ul li.bkmrk { - border-bottom-width: 1px; -} - -#bookmarksBox #topBar *,#bookmarksBox #bookmarksTypeBar *,#bookmarksBox .addForm * { - border-left-width: 1px; -} - -#bookmarksBox #topBar,#bookmarksBox #bookmarksTypeBar,#bookmarksBox .addForm { - border-right-width: 1px; -} - -#bookmarksBox ul .othersBookmarks .bookmarksRemoveFrom,#bookmarksBox ul .bookmarkFolder .folderLabel .bookmarksRemoveFrom { - border-left-width: 0; -} - -#bookmarksShow { - display: block; - position: absolute; - top: 0; - left: 250px; - width: 47px; - margin-top: -100%; - height: 64px; - cursor: pointer; - z-index: 4005; - background-position: center bottom; - background-repeat: no-repeat; - transition: margin-top 100ms ease-in-out; - background-image: url(@@INCLUDEIMAGE:plugins/bookmarks-by-zaso-logo.png@@); -} - -#bookmarksShow: hover { - margin-top: 0!important; -} - -#bookmarkStar { - display: inline-block; - position: relative; - top: 1px; - margin-right: 3px; - width: 16px; - height: 15px; - overflow: hidden; - background-image: url(@@INCLUDEIMAGE:plugins/bookmarks-by-zaso-star.png@@); - background-position: left center; - background-repeat: no-repeat; -} - -#bookmarkStar: hover,#bookmarkStar.favorite { - background-position: right center; -} - -#bookmarksBox .handleScroll { - cursor: s-resize; - width: 3px; - right: 3px; - background: #FFD700; - opacity: .7; -} - -#bookmarksBox .bookmarkList .bookmarkFolder { - overflow: hidden; - margin-top: -1px; - height: auto; - background: rgba(8,58,78,.7); -} - -#bookmarksBox .bookmarkList ul li.sortable-placeholder { - box-shadow: inset -1px 0 0 #20a8b1,inset 1px 0 0 #20a8b1,0 -1px 0 #20a8b1; - background: rgba(8,58,78,.9); -} - -#bookmarksBox .bookmarkList ul li ul li.sortable-placeholder { - height: 23px; - box-shadow: inset 0 -1px 0 #20a8b1,inset 1px 0 0 #20a8b1; -} - -#bookmarksBox .bookmarkList ul li.bookmarkFolder.ui-sortable-helper,#bookmarksBox .bookmarkList ul li.othersBookmarks ul,#bookmarksBox .bookmarkList ul li.othersBookmarks ul li.sortable-placeholder { - box-shadow: inset 0 -1px 0 #20a8b1; -} - -#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span,#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span,#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span,#bookmarksBox .bookmarkList .triangle { - width: 0; - height: 0; -} - -#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel { - overflow: visible; - height: 25px; - cursor: pointer; - background: #069; - text-indent: 0; -} - -#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>* { - height: 25px; - float: left; -} - -#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor { - line-height: 25px; - color: #fff; - width: 209px; -} - -#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span { - float: left; - border-color: transparent transparent transparent #FFF; - border-width: 5px 0 5px 7px; - margin: 7px 7px 0 6px; -} - -#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel .bookmarksAnchor span { - border-color: #FFF transparent transparent; - border-width: 7px 5px 0; - margin: 9px 5px 0; -} - -#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span,#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span { - display: none; - position: relative; - top: 21px; - left: 219px; - border-color: transparent #20a8b1 transparent transparent; - border-width: 0 12px 10px 0; - margin: -20px 0 0; -} - -#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span { - top: 18px; - left: 0; - border-color: transparent #069 transparent transparent; - border-width: 0 10px 9px 0; -} - -#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel: hover>span>span { - border-color: transparent #036 transparent transparent; -} - -#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel: hover .bookmarksAnchor { - background: #036; -} - -#bookmarksBox .bookmarkList .bookmarkFolder ul { - display: none; - margin-left: 19px; -} - -#bookmarksBox .bookmarkList .bookmarkFolder.active ul { - display: block; - min-height: 22px; -} - -#bookmarksBox .bookmarkFolder.othersBookmarks ul { - margin-left: 0; -} - -#bookmarksBox .ui-sortable-helper,#bookmarksBox #topBar,#bookmarksBox ul .bookmarkFolder { - border-top-width: 1px; -} - -#bookmarksBox .bookmarkList.current,#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel>span,#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel>span>span { - display: block; -} - -#bookmarksBox ul .bookmarksLink.selected,#bookmarksBox ul .bookmarksLink: hover { - color: #03fe03; -} - -#bookmarksBox ul .bookmarkFolder,#bookmarksBox ul .bookmarksRemoveFrom,#bookmarksBox .bookmarkList .bkmrk.ui-sortable-helper { - border-right-width: 1px; - border-left-width: 1px; -} diff --git a/plugins/bookmarks-by-zaso.user.js b/plugins/bookmarks-by-zaso.user.js index df6c715e..b8396a9b 100644 --- a/plugins/bookmarks-by-zaso.user.js +++ b/plugins/bookmarks-by-zaso.user.js @@ -1,388 +1,534 @@ // ==UserScript== -// @id iitc-plugin-bookmarks@zaso +// @id iitc-plugin-bookmarks@ZasoGD // @name IITC plugin: Bookmarks for maps and portals -// @version 0.1.3.@@DATETIMEVERSION@@ +// @category Controls +// @version 0.1.55.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ -// @description [@@BUILDNAME@@-@@BUILDDATE@@] Save your favorite Maps and Portals. +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Save your favorite Maps and Portals and move the intelmap view in a second. The ingress world just a click. // @include https://www.ingress.com/intel* // @include http://www.ingress.com/intel* // @match https://www.ingress.com/intel* // @match http://www.ingress.com/intel* // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// + // use own namespace for plugin + window.plugin.bookmarks = function() {}; + window.plugin.bookmarks.bkmrk_portals = {}; + window.plugin.bookmarks.bkmrk_maps = {}; -// use own namespace for plugin -window.plugin.bookmarks = function() {}; + window.plugin.bookmarks.disabledMessage; + window.plugin.bookmarks.contentStarHTML; -window.plugin.bookmarks.KEY_OTHER_BKMRK = 'idOthers'; -window.plugin.bookmarks.LOCAL_STORAGE_status_box = 'plugin-bookmarks-status-box'; -window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_portals = 'plugin-bookmarks-portals-data'; -window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_maps = 'plugin-bookmarks-maps-data'; + window.plugin.bookmarks.KEY_OTHER_BKMRK = 'idOthers'; + window.plugin.bookmarks.LOCAL_STORAGE_status_box = 'plugin-bookmarks-status-box'; + window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_portals = 'plugin-bookmarks-portals-data'; + window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_maps = 'plugin-bookmarks-maps-data'; -window.plugin.bookmarks.bkmrk_portals = {}; -window.plugin.bookmarks.bkmrk_maps = {}; +/*********************************************************************************************************************/ -window.plugin.bookmarks.disabledMessage; -window.plugin.bookmarks.contentStarHTML; -window.plugin.bookmarks.bkmrkBox; -window.plugin.bookmarks.bkmrkRibbon; -window.plugin.bookmarks.loadList; -window.plugin.bookmarks.setupJS; + //--------------------------------------------------------------------------------------- + // Append a 'star' flag in sidebar. + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.addToSidebar = function(){ + if(typeof(Storage) === "undefined"){ $('#portaldetails > .imgpreview').after(plugin.bookmarks.disabledMessage); return; } + $('#portaldetails > h3.title').before(plugin.bookmarks.contentStarHTML); + plugin.bookmarks.updateStarPortal(); + } + + //--------------------------------------------------------------------------------------- + // Update the status of the star (when a portal is selected from the map/bookmarks-list) + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.updateStarPortal = function(){ + window.plugin.bookmarks.loadBookmarks('bkmrk_portals'); + var guid = window.selectedPortal; + $('#bookmarkStar').removeClass('favorite'); + $('.bkmrk a.bookmarksLink.selected').removeClass('selected'); + + //If current portal is into bookmarks: select bookmark portal from portals list and select the star + if(localStorage[window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_portals].search(guid) != -1){ + $('#bookmarkStar').addClass('favorite'); + var list = plugin.bookmarks['bkmrk_portals']; + for(var idFolders in list){ + for(var idBkmrk in list[idFolders]['bkmrk']){ + var portalGuid = list[idFolders]['bkmrk'][idBkmrk]['guid']; + if(guid == portalGuid){ + $('.bkmrk#'+idBkmrk+' a.bookmarksLink').addClass('selected'); + } + } + } + } + } + + //--------------------------------------------------------------------------------------- + // Switch the status of the star + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.switchStarPortal = function(){ + var guid = window.selectedPortal; + + //If portal is saved in bookmarks: Remove this bookmark + if($('#bookmarkStar').hasClass('favorite')){ + var list = plugin.bookmarks['bkmrk_portals']; + + for(var idFolders in list){ + for(var idBkmrk in list[idFolders]['bkmrk']){ + var portalGuid = list[idFolders]['bkmrk'][idBkmrk]['guid']; + if(guid == portalGuid){ + delete list[idFolders]['bkmrk'][idBkmrk]; + $('.bkmrk#'+idBkmrk+'').remove(); + } + } + } + } + //If portal isn't saved in bookmarks: Add this bookmark + else{ + // Get the bookmark data (name, coordinates, portal id) from the portal link + var linka = $('#portaldetails .linkdetails aside a:contains("Portal link")').attr('href'); + var namePortal = $('#portaldetails h3').text(); + var ID = window.plugin.bookmarks.generateID(); + var spac = linka.split('pll='); + var latlng = spac[1] ; + + // Add bookmark in the localStorage + plugin.bookmarks['bkmrk_portals'][plugin.bookmarks.KEY_OTHER_BKMRK]['bkmrk'][ID] = {"guid":guid,"latlng":latlng,"label":namePortal}; + //Append the new bookmark to the map list + $('#bkmrk_portals li.othersBookmarks ul').append('

  • X'+namePortal+'
  • '); + } + window.plugin.bookmarks.storeBookmarks('bkmrk_portals'); + window.plugin.bookmarks.updateStarPortal(); + } + + //--------------------------------------------------------------------------------------- + // Save a bookmark map + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.addBookmarkMap = function(elem){ + // Get the coordinates and zoom level from the permalink + var mapLink = $(elem).attr('href'); + var pars = new RegExp('[\\?&]ll=([^&#]*)[&]z=([^&#]*)').exec(mapLink); + var res = pars[1].split(','); + res[2] = pars[2]; + var latlng = res[0]+','+res[1]; + var zoom = res[2]; + + var ID = window.plugin.bookmarks.generateID(); + + //Get the label | Convert some characters | Set the input (empty) + var nameMap = $(elem).siblings('input').val(); + nameMap = nameMap.replace(/\//g, '/').replace(/\\/g, '\').replace(/"/g, '"').replace(/"/g, '''); + $(elem).siblings('input').val(''); + + // Add bookmark in the localStorage + plugin.bookmarks['bkmrk_maps'][plugin.bookmarks.KEY_OTHER_BKMRK]['bkmrk'][ID] = {"label":nameMap,"latlng":latlng,"z":parseInt(zoom)}; + plugin.bookmarks.storeBookmarks('bkmrk_maps'); + + //Append the new bookmark to the map list + if(nameMap==''){ nameMap = latlng+' ['+zoom+']'; } + $('#bkmrk_maps li.othersBookmarks ul').append('
  • X'+nameMap+'
  • '); + } + +/*********************************************************************************************************************/ + + //--------------------------------------------------------------------------------------- + // Generate an ID for the bookmark (date time + random number) + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.generateID = function(){ + var d = new Date(); + var ID = d.getTime()+(Math.floor(Math.random()*99)+1); + var ID = 'id'+ID.toString(); + return ID; + } + + //--------------------------------------------------------------------------------------- + // Switch the status folder to open/close (in the localStorage) + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.openFolder = function(elem){ + var typeList = $(elem).parent().parent().parent().parent('div').attr('id'); + var ID = $(elem).parent().parent('li').attr('id'); + var newFlag; + var flag = plugin.bookmarks[typeList][ID]['state']; + if(flag){ newFlag = 0; } + else if(!flag){ newFlag = 1; } + window.plugin.bookmarks[typeList][ID]['state'] = newFlag; + window.plugin.bookmarks.storeBookmarks(typeList); + } + + //--------------------------------------------------------------------------------------- + // Switch the status folder to open/close (in the localStorage) + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.addFolder = function(typeList){ + var ID = window.plugin.bookmarks.generateID(); + var input = '#'+typeList+' .addForm input'; + //Get the label | Convert some characters | Set the input (empty) + var nameFolder = $(input).val(); + nameFolder = nameFolder.replace(/\//g, '/').replace(/\\/g, '\').replace(/"/g, '"').replace(/"/g, '''); + if(nameFolder == ''){ nameFolder = 'Folder'; } + $(input).val(''); + + // Add new folder in the localStorage + plugin.bookmarks[typeList][ID] = {"label":nameFolder,"state":1,"bkmrk":{}}; + plugin.bookmarks.storeBookmarks(typeList); + //Append the new folder to the list + $('#'+typeList+' li.othersBookmarks').before('
  • X'+nameFolder+'
    • '); + } + + //--------------------------------------------------------------------------------------- + // Remove the bookmark (from the localStorage) + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.deletBookmark = function(elem){ + 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'); + delete window.plugin.bookmarks[typeList][IDfold]['bkmrk'][ID]; + window.plugin.bookmarks.storeBookmarks(typeList); + if(typeList == 'bkmrk_portals'){ window.plugin.bookmarks.updateStarPortal(); } + } + + //--------------------------------------------------------------------------------------- + // Remove the folder (from the localStorage) + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.deletFolder = function(elem){ + var typeList = $(elem).parent().parent().parent().parent('div').attr('id'); + var ID = $(elem).parent().parent('li').attr('id'); + delete plugin.bookmarks[typeList][ID]; + window.plugin.bookmarks.storeBookmarks(typeList); + if(typeList == 'bkmrk_portals'){ window.plugin.bookmarks.updateStarPortal(); } + } + + //--------------------------------------------------------------------------------------- + // Saved the new sort of the folders (in the localStorage) + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.sortBookmarksFolder = function(typeList){ + window.plugin.bookmarks.loadBookmarks(typeList); + var newArr = {}; + $('#'+typeList+' li.bookmarkFolder').each(function(){ + var idFold = $(this).attr('id'); + newArr[idFold] = window.plugin.bookmarks[typeList][idFold]; + }); + window.plugin.bookmarks[typeList] = newArr; + window.plugin.bookmarks.storeBookmarks(typeList); + } + + //--------------------------------------------------------------------------------------- + // Saved the new sort of the bookmarks (in the localStorage) + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.sortBookmarks = function(typeList){ + window.plugin.bookmarks.loadBookmarks(typeList); + var list = window.plugin.bookmarks[typeList]; + var newArr = {}; + + $('#'+typeList+' li.bookmarkFolder').each(function(){ + var idFold = $(this).attr('id'); + newArr[idFold] = window.plugin.bookmarks[typeList][idFold]; + newArr[idFold].bkmrk = {}; + }); + + $('#'+typeList+' li.bkmrk').each(function(){ + window.plugin.bookmarks.loadBookmarks(typeList); + var idFold = $(this).parent().parent('li').attr('id'); + var id = $(this).attr('id'); + + var list = window.plugin.bookmarks[typeList]; + for(var idFoldersOrigin in list){ + for(var idBkmrk in list[idFoldersOrigin]['bkmrk']){ + if(idBkmrk == id){ + newArr[idFold].bkmrk[id] = window.plugin.bookmarks[typeList][idFoldersOrigin].bkmrk[id]; + } + } + } + }); + window.plugin.bookmarks[typeList] = newArr; + window.plugin.bookmarks.storeBookmarks(typeList); + } + + //--------------------------------------------------------------------------------------- + // Update the localStorage + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.storeBookmarks = function(typeList){ + var bookmarksObject = {}; + bookmarksObject[typeList] = plugin.bookmarks[typeList]; + var bookmarksObjectJSON = JSON.stringify(bookmarksObject); + localStorage[plugin.bookmarks['LOCAL_STORAGE_'+typeList]] = bookmarksObjectJSON; + } + + //--------------------------------------------------------------------------------------- + // Load the localStorage + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.loadBookmarks = function(typeList){ + var bookmarksObjectJSON = localStorage[plugin.bookmarks['LOCAL_STORAGE_'+typeList]]; + if(!bookmarksObjectJSON) return; + var bookmarksObject = JSON.parse(bookmarksObjectJSON); + plugin.bookmarks[typeList] = bookmarksObject[typeList]; + } + + //--------------------------------------------------------------------------------------- + // Load the bookmarks + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.loadList = function(typeList){ + window.plugin.bookmarks.loadBookmarks(typeList); + var element = ''; + var elementTemp = ''; + var elementExc = ''; + + // For each folder + var list = window.plugin.bookmarks[typeList]; + for(var idFolders in list){ + var folders = list[idFolders]; + var active = ''; + + // Create a label and a anchor for the sortable + var folderLabel = 'X'; + folderLabel += ''+folders['label']+''; + + if(folders['state']){ active = ' active'; } + if(idFolders == window.plugin.bookmarks.KEY_OTHER_BKMRK){ + folderLabel = ''; active= ' othersBookmarks active'; + } + // Create a folder + elementTemp = '
    • '+folderLabel+'
        '; + + // For each bookmark + var fold = folders['bkmrk']; + for(var idBkmrk in fold){ + var btn_link; + var btn_remove = 'X'; + var bkmrk = fold[idBkmrk]; + var label = bkmrk['label']; + var latlng = bkmrk['latlng']; + + // If it's a map + if(typeList == 'bkmrk_maps'){ + if(bkmrk['label']==''){ label = bkmrk['latlng']+' ['+bkmrk['z']+']'; } + btn_link = ''+label+''; + } + // If it's a portal + else if(typeList == 'bkmrk_portals'){ + var guid = bkmrk['guid']; + var btn_link = ''+label+''; + } + // Create the bookmark + elementTemp += '
      • '+btn_remove+btn_link+'
      • '; + } + elementTemp += '
      '; + + //Add folder 'Others' in last position + if(idFolders != window.plugin.bookmarks.KEY_OTHER_BKMRK){ element += elementTemp; } + else{ elementExc = elementTemp; } + } + element += elementExc; + + // Append all folders and bookmarks + $('#'+typeList+' ul').html(element); + } + +/*********************************************************************************************************************/ + + //--------------------------------------------------------------------------------------- + // Append the stylesheet + //--------------------------------------------------------------------------------------- + window.plugin.bookmarks.setupCSS = function(){ + $(''); + + +}; + +var setup = window.plugin.miniMap.setup; + +// PLUGIN END ////////////////////////////////////////////////////////// + +@@PLUGINEND@@ diff --git a/plugins/pan-control.user.js b/plugins/pan-control.user.js index 9e8f320d..7e9788cc 100644 --- a/plugins/pan-control.user.js +++ b/plugins/pan-control.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-pan-control@fragger // @name IITC plugin: pan control +// @category Controls // @version 0.1.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -45,16 +43,4 @@ var setup = window.plugin.panControl.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/player-tracker.user.js b/plugins/player-tracker.user.js index 9fc5fdbd..3de0b728 100644 --- a/plugins/player-tracker.user.js +++ b/plugins/player-tracker.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-player-tracker@breunigs // @name IITC Plugin: Player tracker +// @category Layer // @version 0.9.4.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// window.PLAYER_TRACKER_MAX_TIME = 3*60*60*1000; // in milliseconds @@ -411,16 +409,4 @@ var setup = plugin.playerTracker.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/players-resonators.user.js b/plugins/players-resonators.user.js index 0b76bf12..f6647ec2 100644 --- a/plugins/players-resonators.user.js +++ b/plugins/players-resonators.user.js @@ -13,6 +13,10 @@ // @grant none // ==/UserScript== +@@PLUGINSTART@@ + +// PLUGIN START //////////////////////////////////////////////////////// + /********************************************************************************************************* * Changelog: * @@ -24,13 +28,6 @@ * 0.1.0 First public release *********************************************************************************************************/ -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - - -// PLUGIN START //////////////////////////////////////////////////////// - // use own namespace for plugin window.plugin.playersResonators = function() {}; @@ -107,16 +104,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-counts.user.js b/plugins/portal-counts.user.js index 4ef7b6d3..08020cb9 100644 --- a/plugins/portal-counts.user.js +++ b/plugins/portal-counts.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-portals-count@yenky // @name IITC plugin: Show total counts of portals +// @category Info // @version 0.0.8.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,6 +14,10 @@ // @grant none // ==/UserScript== +@@PLUGINSTART@@ + +// PLUGIN START //////////////////////////////////////////////////////// + /* whatsnew * 0.0.8 : use dialog() instead of alert() * 0.0.6 : ignoring outside bounds portals (even if close to) @@ -24,12 +29,6 @@ * todo : */ -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - -// PLUGIN START //////////////////////////////////////////////////////// - // use own namespace for plugin window.plugin.portalcounts = function() {}; @@ -131,16 +130,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-can-make-level.user.js b/plugins/portal-highlighter-can-make-level.user.js index 7a19044d..f4eca8de 100644 --- a/plugins/portal-highlighter-can-make-level.user.js +++ b/plugins/portal-highlighter-can-make-level.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-upgrade@vita10gy // @name IITC plugin: highlight portals you can upgrade to a specific level +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -78,16 +76,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-level-color.user.js b/plugins/portal-highlighter-level-color.user.js index a690d838..ad2e28d1 100644 --- a/plugins/portal-highlighter-level-color.user.js +++ b/plugins/portal-highlighter-level-color.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-level-color@vita10gy // @name IITC plugin: highlight portals by level color +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,14 +14,11 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// -// use own namespace for plugin +// use own namespace for plugin window.plugin.portalHighligherPortalsLevelColor = function() {}; window.plugin.portalHighligherPortalsLevelColor.colorLevel = function(data) { @@ -37,16 +35,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-missing-resonators.user.js b/plugins/portal-highlighter-missing-resonators.user.js index 1103bf85..9457ad42 100644 --- a/plugins/portal-highlighter-missing-resonators.user.js +++ b/plugins/portal-highlighter-missing-resonators.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-missing-resonators@vita10gy // @name IITC plugin: highlight portals missing resonators +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -63,16 +61,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-mods.user.js b/plugins/portal-highlighter-mods.user.js new file mode 100644 index 00000000..0bdcd41c --- /dev/null +++ b/plugins/portal-highlighter-mods.user.js @@ -0,0 +1,70 @@ +// ==UserScript== +// @id iitc-plugin-highlight-portals-mods@vita10gy +// @name IITC plugin: highlight portal mods +// @category Highlighter +// @version 0.1.0.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote if the portal has the selected mod. +// @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.portalHighligherMods = function() {}; + +window.plugin.portalHighligherMods.highlight = function(data, mod_type) { + var d = data.portal.options.details; + + var mod_effect = 0; + $.each(d.portalV2.linkedModArray, function(ind, mod) { + if(mod !== null && mod.type == mod_type) { + switch(mod.rarity){ + case 'COMMON': + mod_effect++; + break; + case 'RARE': + mod_effect+=2; + break; + case 'VERY_RARE': + mod_effect+=3; + break; + } + } + }); + + if(mod_effect > 0) { + var fill_opacity = mod_effect/12*.85 + .15; + var color = 'red'; + fill_opacity = Math.round(fill_opacity*100)/100; + var params = {fillColor: color, fillOpacity: fill_opacity}; + data.portal.setStyle(params); + } + + window.COLOR_SELECTED_PORTAL = '#f0f'; +} + +window.plugin.portalHighligherMods.getHighlighter = function(type) { + return(function(data){ + window.plugin.portalHighligherMods.highlight(data,type); + }); +} + + +var setup = function() { + $.each(MOD_TYPE, function(ind, name){ + window.addPortalHighlighter('Mod: '+name, window.plugin.portalHighligherMods.getHighlighter(ind)); + }); +} + +// PLUGIN END ////////////////////////////////////////////////////////// + +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-my-8-portals.user.js b/plugins/portal-highlighter-my-8-portals.user.js index ea63515f..11b6f6f7 100644 --- a/plugins/portal-highlighter-my-8-portals.user.js +++ b/plugins/portal-highlighter-my-8-portals.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-my-8-portals@vita10gy // @name IITC plugin: highlight my level 8's on portals +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -53,16 +51,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-my-portals.user.js b/plugins/portal-highlighter-my-portals.user.js index 505c9e4c..09d208b6 100644 --- a/plugins/portal-highlighter-my-portals.user.js +++ b/plugins/portal-highlighter-my-portals.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-my-portals@vita10gy // @name IITC plugin: highlight my portals +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -73,16 +71,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-needs-recharge.user.js b/plugins/portal-highlighter-needs-recharge.user.js index b5cd8689..63422ec2 100644 --- a/plugins/portal-highlighter-needs-recharge.user.js +++ b/plugins/portal-highlighter-needs-recharge.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-needs-recharge@vita10gy // @name IITC plugin: hightlight portals that need recharging +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -46,16 +44,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-portal-ap-energy-relative.user.js b/plugins/portal-highlighter-portal-ap-energy-relative.user.js index 02ba2a8a..a4e53cb6 100644 --- a/plugins/portal-highlighter-portal-ap-energy-relative.user.js +++ b/plugins/portal-highlighter-portal-ap-energy-relative.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-by-ap-by-energy-relative@vita10gy // @name IITC plugin: highlight portals by ap/energy (relative) +// @category Highlighter // @version 0.1.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -104,16 +102,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-portal-ap-relative.user.js b/plugins/portal-highlighter-portal-ap-relative.user.js index 5bade6b6..f6c1cbf6 100644 --- a/plugins/portal-highlighter-portal-ap-relative.user.js +++ b/plugins/portal-highlighter-portal-ap-relative.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-by-ap-relative@vita10gy // @name IITC plugin: highlight portals by ap relative +// @category Highlighter // @version 0.1.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -99,16 +97,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-portal-ap.user.js b/plugins/portal-highlighter-portal-ap.user.js index 0441fdc6..5b907248 100644 --- a/plugins/portal-highlighter-portal-ap.user.js +++ b/plugins/portal-highlighter-portal-ap.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-by-ap@vita10gy // @name IITC plugin: highlight portals by ap +// @category Highlighter // @version 0.1.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -60,16 +58,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-portals-my-level.user.js b/plugins/portal-highlighter-portals-my-level.user.js index 32d1fa47..dddd1a2b 100644 --- a/plugins/portal-highlighter-portals-my-level.user.js +++ b/plugins/portal-highlighter-portals-my-level.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-my-level@vita10gy // @name IITC plugin: highlight portals by my level +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -54,16 +52,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-portals-upgrade.user.js b/plugins/portal-highlighter-portals-upgrade.user.js index e8238e6f..569a1347 100644 --- a/plugins/portal-highlighter-portals-upgrade.user.js +++ b/plugins/portal-highlighter-portals-upgrade.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-upgrade@vita10gy // @name IITC plugin: highlight portals you can upgrade +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -57,16 +55,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-highlighter-with-lvl8-resonators.user.js b/plugins/portal-highlighter-with-lvl8-resonators.user.js index 7b29a018..01889199 100644 --- a/plugins/portal-highlighter-with-lvl8-resonators.user.js +++ b/plugins/portal-highlighter-with-lvl8-resonators.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-highlight-portals-with-L8-resonators@superd // @name IITC plugin: highlight portals with L8 resonators +// @category Highlighter // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -54,16 +52,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portal-level-numbers.user.js b/plugins/portal-level-numbers.user.js index 349c1fd0..532d78a9 100644 --- a/plugins/portal-level-numbers.user.js +++ b/plugins/portal-level-numbers.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-portal-level-numbers@rongou // @name IITC plugin: Portal Level Numbers +// @category Layer // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -85,16 +83,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/portals-list.user.js b/plugins/portals-list.user.js index 1b33644a..7c79cc49 100644 --- a/plugins/portals-list.user.js +++ b/plugins/portals-list.user.js @@ -1,7 +1,8 @@ // ==UserScript== // @id iitc-plugin-portals-list@teo96 // @name IITC plugin: show list of portals -// @version 0.0.13.@@DATETIMEVERSION@@ +// @category Info +// @version 0.0.14.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -13,7 +14,12 @@ // @grant none // ==/UserScript== +@@PLUGINSTART@@ + +// PLUGIN START //////////////////////////////////////////////////////// + /* whatsnew +* 0.0.14: Add support to new mods (S:Shield - T:Turret - LA:Link Amp - H:Heat-sink - M:Multi-hack - FA:Force Amp) * 0.0.12: Use dialog() instead of alert so the user can drag the box around * 0.0.11: Add nominal energy column and # links, fix sort bug when opened even amounts of times, nits * 0.0.10: Fixed persistent css problem with alert @@ -33,12 +39,6 @@ * todo : export as GPX, Open in Google Maps, more statistics in the header, what else ? */ -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - -// PLUGIN START //////////////////////////////////////////////////////// - // use own namespace for plugin window.plugin.portalslist = function() {}; @@ -94,19 +94,44 @@ window.plugin.portalslist.getPortals = function() { // Sort resonators array by resonator level resonators.sort(function (a, b) {return b[0] - a[0]}); - //get shield informations - var shields = []; + //get mods informations + var mods = []; $.each(d.portalV2.linkedModArray, function(ind, mod) { - if (mod) { - //shields[ind] = mod.rarity.capitalize().replace('_', ' '); - shields[ind] = [mod.rarity.substr(0,1).capitalize(), getPlayerName(mod.installingUser)] ; - } else { - shields[ind] = ['', '']; - } + var modShortName=''; + if (mod) { + switch (mod.displayName) { + case 'Portal Shield': + modShortName = 'S'; + break; + case 'Force Amp': + modShortName = 'FA'; + break; + case 'Link Amp': + modShortName = 'LA'; + break; + case 'Heat Sink': + modShortName = 'H'; + break; + case 'Multi-hack': + modShortName = 'M'; + break; + case 'Turret': + modShortName = 'T'; + break; + default: + modShortName = ''; + break; + } + if (modShortName === '') { + mods[ind] = ['', '', '']; + } else { + mods[ind] = [mod.rarity, getPlayerName(mod.installingUser), modShortName, mod.displayName]; + } + }else { mods[ind] = ['', '', '']; } }); - + console.log(mods); var APgain= getAttackApGain(d).enemyAp; - var thisPortal = {'portal': d, 'name': name, 'team': team, 'level': level, 'guid': guid, 'resonators': resonators, 'energyratio': maxenergy ? Math.floor(energy/maxenergy*100) : 0, 'shields': shields, 'APgain': APgain, 'EAP': (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy': maxenergy, 'links': d.portalV2.linkedEdges.length, 'lat': portal._latlng.lat, 'lng': portal._latlng.lng, 'address': address, 'img': img}; + var thisPortal = {'portal': d, 'name': name, 'team': team, 'level': level, 'guid': guid, 'resonators': resonators, 'energyratio': maxenergy ? Math.floor(energy/maxenergy*100) : 0, 'mods': mods, 'APgain': APgain, 'EAP': (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy': maxenergy, 'links': d.portalV2.linkedEdges.length, 'lat': portal._latlng.lat, 'lng': portal._latlng.lng, 'address': address, 'img': img}; window.plugin.portalslist.listPortals.push(thisPortal); }); @@ -199,16 +224,16 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { retVal = b.resonators[7][0] - a.resonators[7][0]; break; case 's1': - retVal = a.shields[0].toLowerCase() > b.shields[0].toLowerCase() ? -1 : 1; + retVal = a.mods[0][2] > b.mods[0][2] ? -1 : 1; break; case 's2': - retVal = a.shields[1].toLowerCase() > b.shields[1].toLowerCase() ? -1 : 1; + retVal = a.mods[1][2] > b.mods[1][2] ? -1 : 1; break; case 's3': - retVal = a.shields[2].toLowerCase() > b.shields[2].toLowerCase() ? -1 : 1; + retVal = a.mods[2][2] > b.mods[2][2] ? -1 : 1; break; case 's4': - retVal = a.shields[3].toLowerCase() > b.shields[3].toLowerCase() ? -1 : 1; + retVal = a.mods[3][2] > b.mods[3][2] ? -1 : 1; break; default: retVal = b[sortBy] - a[sortBy]; @@ -235,10 +260,10 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { + 'Energy' + '%' + 'Links' - + 'S1' - + 'S2' - + 'S3' - + 'S4' + + 'M1' + + 'M2' + + 'M3' + + 'M4' + 'AP Gain' + 'E/AP'; @@ -263,13 +288,13 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { }); - html += '' + prettyEnergy(portal.energy) + '' + html += '' + prettyEnergy(portal.energy) + '' + '' + portal.energyratio + '%' + '' + portal.links + '' - + '' + portal.shields[0][0] + '' - + '' + portal.shields[1][0] + '' - + '' + portal.shields[2][0] + '' - + '' + portal.shields[3][0] + '' + + '' + portal.mods[0][2] + '' + + '' + portal.mods[1][2] + '' + + '' + portal.mods[2][2] + '' + + '' + portal.mods[3][2] + '' + '' + portal.APgain + '' + '' + portal.EAP + ''; @@ -363,16 +388,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/privacy-view.user.js b/plugins/privacy-view.user.js index 8a400335..92daeede 100644 --- a/plugins/privacy-view.user.js +++ b/plugins/privacy-view.user.js @@ -13,11 +13,7 @@ // @grant none // ==/UserScript== -function wrapper() { - -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') - window.plugin = function() {}; +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -114,18 +110,4 @@ var setup = window.plugin.privacyView.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} - -} // wrapper end - -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/render-limit-increase.user.js b/plugins/render-limit-increase.user.js index d3b43039..752f2629 100644 --- a/plugins/render-limit-increase.user.js +++ b/plugins/render-limit-increase.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-render-limit-increase@jonatkins // @name IITC plugin: render limit increase +// @category Tweaks // @version 0.3.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,8 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -49,16 +48,4 @@ var setup = window.plugin.renderLimitIncrease.setHigherLimits; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/reso-energy-pct-in-portal-detail.user.js b/plugins/reso-energy-pct-in-portal-detail.user.js index 226d5ced..1120167c 100644 --- a/plugins/reso-energy-pct-in-portal-detail.user.js +++ b/plugins/reso-energy-pct-in-portal-detail.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-reso-energy-pct-in-portal-detail@xelio // @name IITC plugin: reso energy pct in portal detail +// @category Portal Info // @version 0.1.2.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -46,16 +44,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/resonator-display-zoom-level-decrease.user.js b/plugins/resonator-display-zoom-level-decrease.user.js index d1fb272f..82b08c28 100644 --- a/plugins/resonator-display-zoom-level-decrease.user.js +++ b/plugins/resonator-display-zoom-level-decrease.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-resonator-display-zoom-level-decrease@xelio // @name IITC plugin: resonator display zoom level decrease +// @category Tweaks // @version 1.0.2.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -34,16 +32,4 @@ var setup = window.plugin.resonatorDisplayZoomLevelDecrease.changeConstant; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/scale-bar.user.js b/plugins/scale-bar.user.js index 0a451357..26830c75 100644 --- a/plugins/scale-bar.user.js +++ b/plugins/scale-bar.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-scale-bar@breunigs // @name IITC plugin: scale bar +// @category Controls // @version 0.1.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -41,16 +39,4 @@ var setup = window.plugin.scaleBar.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/scoreboard.user.js b/plugins/scoreboard.user.js index ddd8de61..c449c28a 100644 --- a/plugins/scoreboard.user.js +++ b/plugins/scoreboard.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-scoreboard@vita10gy // @name IITC plugin: show a localized scoreboard. +// @category Info // @version 0.1.8.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -426,16 +424,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/scroll-wheel-zoom-disable.user.js b/plugins/scroll-wheel-zoom-disable.user.js new file mode 100644 index 00000000..e7e66c9a --- /dev/null +++ b/plugins/scroll-wheel-zoom-disable.user.js @@ -0,0 +1,36 @@ +// ==UserScript== +// @id iitc-plugin-scroll-wheel-zoom-disable@jonatkins +// @name IITC plugin: disable mouse wheel zoom +// @category Tweaks +// @version 0.1.0.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Disable the use of mouse wheel to zoom. The map zoom controls or keyboard are still available. +// @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.scrollWheelZoomDisable = function() {}; + +window.plugin.scrollWheelZoomDisable.setup = function() { + + window.map.scrollWheelZoom.disable(); + +}; + +var setup = window.plugin.scrollWheelZoomDisable.setup; + +// PLUGIN END ////////////////////////////////////////////////////////// + +@@PLUGINEND@@ diff --git a/plugins/show-address.user.js b/plugins/show-address.user.js index 488159bd..62f0ab5a 100644 --- a/plugins/show-address.user.js +++ b/plugins/show-address.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-show-address@vita10gy // @name IITC plugin: show portal address in sidebar +// @category Portal Info // @version 0.2.2.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -43,16 +41,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/show-linked-portals.user.js b/plugins/show-linked-portals.user.js index b118acf0..39392060 100644 --- a/plugins/show-linked-portals.user.js +++ b/plugins/show-linked-portals.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-show-linked-portals@fstopienski // @name IITC plugin: Show linked portals +// @category Portal Info // @version 0.0.4.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,21 +14,16 @@ // @grant none // ==/UserScript== +@@PLUGINSTART@@ + +// PLUGIN START //////////////////////////////////////////////////////// + /* * 0.0.1 initial release, show images, names and addresses of linked portal in portal detailview * - mouse click of the linked portal image selected the portal and adjust map * - click of "Linked Portal is out of range" zoom a step out */ -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if (typeof window.plugin !== 'function') { - window.plugin = function () { - }; -} - -// PLUGIN START //////////////////////////////////////////////////////// - // use own namespace for plugin window.plugin.showLinkedPortal = function () { }; @@ -120,16 +116,4 @@ var setup = function () { } // PLUGIN END ////////////////////////////////////////////////////////// -if (window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if (window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/show-more-portals.user.js b/plugins/show-more-portals.user.js new file mode 100644 index 00000000..998f33a4 --- /dev/null +++ b/plugins/show-more-portals.user.js @@ -0,0 +1,61 @@ +// ==UserScript== +// @id iitc-plugin-show-more-portals@jonatkins +// @name IITC plugin: Show more portals +// @category Tweaks +// @version 0.1.0.@@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. Good for small screens. Likely to increase request failed errors on larger screens. +// @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.showMorePortals = function() {}; + +window.plugin.showMorePortals.setup = function() { + + // replace the window.getPortalDataZoom function + + window.getPortalDataZoom = function() { + var mapZoom = map.getZoom(); + + // yes, it is possible to increase this beyond "+1" - however, that will end up producing a rediculous number + // of requests to the Niantic servers, giving many request failed errors/tile timeouts + // (every increase by one requests four times as many data tiles) + var z = mapZoom + 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; + } + + //sanity check - should never happen + if (z < 0) z=0; + + return z; + } + + +}; + +var setup = window.plugin.showMorePortals.setup; + +// PLUGIN END ////////////////////////////////////////////////////////// + +@@PLUGINEND@@ diff --git a/plugins/show-portal-weakness.user.js b/plugins/show-portal-weakness.user.js index c2809e7f..93742b1c 100644 --- a/plugins/show-portal-weakness.user.js +++ b/plugins/show-portal-weakness.user.js @@ -1,11 +1,12 @@ // ==UserScript== // @id iitc-plugin-show-portal-weakness@vita10gy // @name IITC plugin: show portal weakness -// @version 0.7.0.@@DATETIMEVERSION@@ +// @category Highlighter +// @version 0.7.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ -// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote if the portal is weak (Needs recharging, missing a resonator, needs shields) Red, needs energy and shields. Orange, only needs energy (either recharge or resonators). Yellow, only needs shields. +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote if the portal is weak (Needs recharging, missing a resonator, needs mods) Red, needs energy and mods. Orange, only needs energy (either recharge or resonators). Yellow, only needs mods. // @include https://www.ingress.com/intel* // @include http://www.ingress.com/intel* // @match https://www.ingress.com/intel* @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -27,17 +25,19 @@ window.plugin.portalWeakness.highlightWeakness = function(data) { var d = data.portal.options.details; var portal_weakness = 0; if(getTeam(d) !== 0) { - var only_shields = true; - var missing_shields = 0; + var only_mods = true; + var missing_mods = 0; if(window.getTotalPortalEnergy(d) > 0 && window.getCurrentPortalEnergy(d) < window.getTotalPortalEnergy(d)) { portal_weakness = 1 - (window.getCurrentPortalEnergy(d)/window.getTotalPortalEnergy(d)); - only_shields = false; + only_mods = false; } - //Ding the portal for every missing sheild. + //Ding the portal for every unapplicable mod. $.each(d.portalV2.linkedModArray, function(ind, mod) { - if(mod === null) { - missing_shields++; - portal_weakness += .03; + if(mod === null || mod.type == 'MULTIHACK' || mod.type == 'HEATSINK' || mod.type == 'LINK_AMPLIFIER') { + if(mod === null) { + missing_mods++; + } + portal_weakness += .08; } }); //Ding the portal for every missing resonator. @@ -45,7 +45,7 @@ window.plugin.portalWeakness.highlightWeakness = function(data) { $.each(d.resonatorArray.resonators, function(ind, reso) { if(reso === null) { portal_weakness += .125; - only_shields = false; + only_mods = false; } else { resCount++; } @@ -60,12 +60,12 @@ window.plugin.portalWeakness.highlightWeakness = function(data) { if(portal_weakness > 0) { var fill_opacity = portal_weakness*.85 + .15; var color = 'orange'; - if(only_shields) { + if(only_mods) { color = 'yellow'; - //If only shields are missing, make portal yellow + //If only mods are missing, make portal yellow // but fill more than usual since pale yellow is basically invisible - fill_opacity = missing_shields*.15 + .1; - } else if(missing_shields > 0) { + fill_opacity = missing_mods*.15 + .1; + } else if(missing_mods > 0) { color = 'red'; } fill_opacity = Math.round(fill_opacity*100)/100; @@ -91,16 +91,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/speech-search.user.js b/plugins/speech-search.user.js index 408be363..589f785c 100644 --- a/plugins/speech-search.user.js +++ b/plugins/speech-search.user.js @@ -13,10 +13,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if (typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -36,16 +33,4 @@ var setup = window.plugin.speechSearch.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/sync.user.js b/plugins/sync.user.js index 248da344..9f90b9cb 100644 --- a/plugins/sync.user.js +++ b/plugins/sync.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-sync@xelio // @name IITC plugin: Sync +// @category Keys // @version 0.2.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -753,16 +751,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/plugins/zoom-slider.user.js b/plugins/zoom-slider.user.js index 01e4269e..d54e4be0 100644 --- a/plugins/zoom-slider.user.js +++ b/plugins/zoom-slider.user.js @@ -1,6 +1,7 @@ // ==UserScript== // @id iitc-plugin-zoom-slider@fragger // @name IITC plugin: zoom slider +// @category Controls // @version 0.1.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ @@ -13,10 +14,7 @@ // @grant none // ==/UserScript== -function wrapper() { -// ensure plugin framework is there, even if iitc is not yet loaded -if(typeof window.plugin !== 'function') window.plugin = function() {}; - +@@PLUGINSTART@@ // PLUGIN START //////////////////////////////////////////////////////// @@ -41,16 +39,4 @@ var setup = window.plugin.zoomSlider.setup; // PLUGIN END ////////////////////////////////////////////////////////// -if(window.iitcLoaded && typeof setup === 'function') { - setup(); -} else { - if(window.bootPlugins) - window.bootPlugins.push(setup); - else - window.bootPlugins = [setup]; -} -} // wrapper end -// inject code into site context -var script = document.createElement('script'); -script.appendChild(document.createTextNode('('+ wrapper +')();')); -(document.body || document.head || document.documentElement).appendChild(script); +@@PLUGINEND@@ diff --git a/style.css b/style.css index 69dbbd8c..43a4d398 100644 --- a/style.css +++ b/style.css @@ -514,6 +514,10 @@ h3 { display: none; } +.imgpreview .portalDetails { + display: none; +} + #level { font-size: 40px; text-shadow: -1px -1px #000, 1px -1px #000, -1px 1px #000, 1px 1px #000, 0 0 5px #fff; @@ -824,6 +828,7 @@ h3 { overflow-x: hidden; max-height: 600px !important; max-width: 700px !important; + position: relative; } .ui-dialog-content-hidden { @@ -938,3 +943,17 @@ td + td { } + +.portal_details th, .portal_details td { + vertical-align: top; + text-align: left; +} + +.portal_details th { + white-space: nowrap; + padding-right: 1em; +} + +.portal_details tr.padding-top th, .portal_details tr.padding-top td { + padding-top: 0.7em; +} diff --git a/website/assets/css/style.css b/website/assets/css/style.css index e2896528..8ab26fde 100644 --- a/website/assets/css/style.css +++ b/website/assets/css/style.css @@ -3,3 +3,7 @@ body { background: url('../img/bg.jpg'); } + +table tr.category_header { + background: #ddd; +} diff --git a/website/page/code/desktop-download.php b/website/page/code/desktop-download.php index 9845d07e..c91986c0 100644 --- a/website/page/code/desktop-download.php +++ b/website/page/code/desktop-download.php @@ -16,8 +16,41 @@ function iitcDesktopDownload ( $build ) function iitcDesktopPluginDownloadTable ( $build ) { + $categories = Array ( + 'Portal Info' => "Enhanced information on the selected portal", + 'Info' => "Display additional information", + 'Keys' => "Manual key management", + 'Controls' => "Map controls/widgets", + 'Highlighter' => "Portal highlighters", + 'Layer' => "Additional map layers", + 'Map Tiles' => "Alternative map layers", + 'Tweaks' => "Adjust IITC settings", + 'Misc' => "Unclassified plugins", + ); + + $plugins = Array(); + + foreach ( glob ( "$build/plugins/*.user.js" ) as $path ) + { + $basename = basename ( $path, ".user.js" ); + $details = loadUserScriptHeader ( $path ); + + $plugins[$basename] = $details; + + $category = array_key_exists('@category',$details) ? $details['@category'] : 'Misc'; + + if ( !array_key_exists($category,$categories) ) + { + # add missing categories + $categories[$category] = ''; + } + } + + ksort ( $plugins ); + + ?> - +
      @@ -29,30 +62,43 @@ function iitcDesktopPluginDownloadTable ( $build ) $category_desc ) + { + print "\n"; - $details = loadUserScriptHeader ( $path ); + $empty = True; + foreach ( $plugins as $basename => $details ) + { + $path = "$build/plugins/$basename.user.js"; - print "\n"; + $this_category = array_key_exists('@category',$details) ? $details['@category'] : 'Misc'; - # remove 'IITC Plugin: ' prefix if it's there, for neatness - $name = preg_replace ( '/^IITC plugin: /i', '', $details['@name'] ); + if ( $category != $this_category ) + continue; - # format extended version info in less prominant font - $version = preg_replace ( '/^(\d+\.\d+\.\d+)\.(\d{8}\.\d{6})/', '\1.\2', $details['@version'] ); + $empty = False; - # remove unneeded prefix from description - $description = preg_replace ( '/^\[[^]]*\] */', '', $details['@description'] ); + print "\n"; - print ""; - print ""; - print ""; - print ""; - print "\n"; -} + # remove 'IITC Plugin: ' prefix if it's there, for neatness + $name = preg_replace ( '/^IITC plugin: /i', '', $details['@name'] ); + # format extended version info in less prominant font + $version = preg_replace ( '/^(\d+\.\d+\.\d+)\.(\d{8}\.\d{6})/', '\1.\2', $details['@version'] ); + + # remove unneeded prefix from description + $description = preg_replace ( '/^\[[^]]*\] */', '', $details['@description'] ); + + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + if ( $empty ) + print "\n"; + + } ?>
      Name
      Category: $category$category_desc
      $name$basename
      $version
      $descriptionDownload
      $name$basename
      $version
      $descriptionDownload
      (no plugins in this category)
      diff --git a/website/page/home.php b/website/page/home.php index 07a8b8e1..1bc21387 100644 --- a/website/page/home.php +++ b/website/page/home.php @@ -13,21 +13,25 @@ offers many more features. It is available for

      Latest news

      - -

      22nd May 2013

      +

      1st July 2013

      -IITC version 0.12.0 has been released. This contains quite a few changes and new features, including +IITC version 0.12.2 released, and IITC Mobile 0.4.8.

        -
      • Portal highlighter system - and many portal highlighter plugins
      • -
      • Dialogs - can be kept open and dragged while viewing the map
      • -
      • Layers - the enabled layers are now remembered when you next load the intel site
      • -
      • Improved request limits - more improvements have been made in this area
      • -
      • Sync plugin - to sync data from the 'Keys' addon to multiple computers via Google Drive
      • -
      • ... and many other tweaks, bug fixes, etc
      • +
      • Various internal improvements to reduce requests to the Niantic servers and improve performance; +a data tile cache, and fixes to idle code when the user isn't interacting.
      • +
      • Improved display of stats for the new mods.
      • +
      • Portal range calculation now includes boost from link amps.
      • +
      • Removed 'redeem code' input box - not sure when it's returning.
      • +
      +Plugin changes: +
        +
      • Guess player levels - option to reset guesses.
      • +
      • New highlighter plugins for the new mods.
      • +
      • Max-links plugin - fixed problems with very narrow triangles causing overlapping links sometimes.
      • +
      • Portals-list plugin - support for the new mods.
      • +
      • Show portal weakness plugin - tweaks to highlight portals with non-defensive mods.
      • +
      • Plugin to show increased portal detail (intended for mobile and smaller screens. Can cause more errors on larger screens)
      -IITC Mobile 0.4.0 is also released. THis has also had major work. Along with the above, it includes a -new in-app layer chooser and chat/map switcher, and authentication has been revamped to use the native -Android authentication rather than entering your password.

      Older news diff --git a/website/page/news.php b/website/page/news.php index fdec6933..f0a2a88a 100644 --- a/website/page/news.php +++ b/website/page/news.php @@ -1,5 +1,41 @@

      News

      +

      1st July 2013

      +

      +IITC version 0.12.2 released, and IITC Mobile 0.4.8. +

        +
      • Various internal improvements to reduce requests to the Niantic servers and improve performance; +a data tile cache, and fixes to idle code when the user isn't interacting.
      • +
      • Improved display of stats for the new mods.
      • +
      • Portal range calculation now includes boost from link amps.
      • +
      • Removed 'redeem code' input box - not sure when it's returning.
      • +
      +Plugin changes: +
        +
      • Guess player levels - option to reset guesses.
      • +
      • New highlighter plugins for the new mods.
      • +
      • Max-links plugin - fixed problems with very narrow triangles causing overlapping links sometimes.
      • +
      • Portals-list plugin - support for the new mods.
      • +
      • Show portal weakness plugin - tweaks to highlight portals with non-defensive mods.
      • +
      • Plugin to show increased portal detail (intended for mobile and smaller screens. Can cause more errors on larger screens)
      • +
      +

      + +

      12th June 2013

      +

      +IITC version 0.12.1 released, and IITC Mobile 0.4.6. Changes include: +

        +
      • Display details about the new portal mods
      • +
      • Updated Leaflet.js version - may reduce issues found on some Samsung devices running Android 4.1 (Jellybean)
      • +
      • Fix resolving a large number of player names in one go
      • +
      • Prevent refreshing old chat messages on small map movements - can vastly reduce repeated requests in some cases
      • +
      • Various improvements/tweaks to the mobile version
      • +
      • AP list plugin: fixed shield mitigation calculation
      • +
      • New basemap plugins: OpenStreetMap, OpenCycleMap, Yandex (Russian), and a template for CloudMade.com to restore the original blue map
      • +
      • Guess player level plugin: attempt to spot when a Jarvis Virus/ADA Refactor has been used and ignore that player's resonators when guessing the level
      • +
      • Max links plugin: optimisations and dashed lines
      • +
      +

      22nd May 2013

      IITC version 0.12.0 has been released. This contains quite a few changes and new features, including