Merge pull request #1 from jonatkins/master

updated to newest code
This commit is contained in:
reckter 2015-05-01 20:30:44 +02:00
commit 98d50fe66d
124 changed files with 1942 additions and 76 deletions

View File

@ -149,6 +149,7 @@ window.artifact.getArtifactDescriptions = function(type) {
'amar': { 'title': "Amar Artifacts", 'fragmentName': "artifacts" },
'helios': { 'title': "Helios Artifacts", 'fragmentName': "artifacts" },
'shonin': { 'title': "Sh\u014Dnin Shards", 'fragmentName': "shards" },
'lightman': { 'title': "Lightman Shards", 'fragmentName': "shards" },
};
return descriptions[type];
@ -223,7 +224,6 @@ window.artifact.updateLayer = function() {
iconSize = 60/2; // 60 pixels - half that size works better
opacity = 0.6; // these often hide portals - let's make them semi transparent
}
}
// 2014-08-09 - helios artifacts. original guess was slightly wrong
@ -237,7 +237,6 @@ window.artifact.updateLayer = function() {
iconSize = 60/2; // 60 pixels - half that size works better
opacity = 0.6; // these often hide portals - let's make them semi transparent
}
}
// 2015-03-05 - shonin shards
@ -251,7 +250,19 @@ window.artifact.updateLayer = function() {
iconSize = 60/2; // 60 pixels - half that size works better
opacity = 0.6; // these often hide portals - let's make them semi transparent
}
}
// 2015-04-22 - lightman fragments (guessed)
if (data.lightman) {
if (data.lightman.target) {
// target portal - show the target marker.
iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/lightman_shard_target.png';
iconSize = 100/2; // 100 pixels - half that size works better
} else if (data.lightman.fragments) {
iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/lightman_shard.png';
iconSize = 60/2; // 60 pixels - half that size works better
opacity = 0.6; // these often hide portals - let's make them semi transparent
}
}
if (iconUrl) {

View File

@ -165,7 +165,7 @@ window.setupMap = function() {
center: [0,0],
zoom: 1,
zoomControl: (typeof android !== 'undefined' && android && android.showZoom) ? android.showZoom() : true,
minZoom: 5,
minZoom: MIN_ZOOM,
// zoomAnimation: false,
markerZoomAnimation: false,
bounceAtZoomLimits: false
@ -591,6 +591,7 @@ function boot() {
window.setupTaphold();
window.setupStyles();
window.setupDialogs();
window.setupDataTileParams();
window.setupMap();
window.setupOMS();
window.search.setup();

View File

@ -116,12 +116,9 @@ iitc_bg.process_key = function(key,serverEval) {
if (serverEval) {
// server wants us to eval some code! risky, and impossible to be certain we can do it safely
// however... reports say that it only interacts with the botguard.bg code, so we might be fine just running it
// (but this is only when we don't send the correct params to the server? no reports of this code triggering yet...)
// seems to always be the same javascript as already found in the web page source.
try {
console.warn('botguard: Server-generated javascript eval requested:\n'+serverEval);
debugger;
if (!confirm('The server asked IITC to run (eval) some javascript. This may or may not be safe. Run and continue?\n\nScript:\n'+serverEval)) { console.error('server javascript eval cancelled') } else
iitc_bg.evalFunc(serverEval);
console.log('botguard: Server-generated javascript ran OK');
} catch(e) {

View File

@ -76,7 +76,7 @@ window.extractFromStock = function() {
// a reasonable array length for tile parameters
// need to find two types:
// a. portal level limits. decreasing numbers, starting at 8
// b. tiles per edge. increasing numbers. current max is 9000
// b. tiles per edge. increasing numbers. current max is 36000, 9000 was the previous value - 18000 is a likely possibility too
if (topObject[0] == 8) {
// check for tile levels
@ -93,7 +93,7 @@ window.extractFromStock = function() {
}
} // end if (topObject[0] == 8)
if (topObject[topObject.length-1] == 9000) {
if (topObject[topObject.length-1] == 36000 || topObject[topObject.length-1] == 18000 || topObject[topObject.length-1] == 9000) {
var increasing = true;
for (var i=1; i<topObject.length; i++) {
if (topObject[i-1] > topObject[i]) {

View File

@ -10,38 +10,84 @@
// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
window.getMapZoomTileParameters = function(zoom) {
window.setupDataTileParams = function() {
// default values - used to fall back to if we can't detect those used in stock intel
var DEFAULT_ZOOM_TO_TILES_PER_EDGE = [256, 256, 256, 256, 512, 512, 512, 2048, 2048, 2048, 4096, 4096, 6500, 6500, 6500, 18e3, 18e3, 36e3];
var DEFAULT_ZOOM_TO_LEVEL = [ 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1, 1 ];
// var ZOOM_TO_TILES_PER_EDGE = [64, 64, 128, 128, 256, 256, 256, 1024, 1024, 1536, 4096, 4096, 6500, 6500, 6500];
// var ZOOM_TO_TILES_PER_EDGE = [256, 256, 256, 256, 512, 512, 512, 2048, 2048, 2048, 4096, 4096, 6500, 6500, 6500];
var ZOOM_TO_TILES_PER_EDGE = [256, 256, 256, 256, 512, 2048, 2048, 4096, 4096, 4096, 4096, 4096, 6500, 6500, 6500];;
var MAX_TILES_PER_EDGE = 9000;
// var ZOOM_TO_LEVEL = [8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1, 1];
var ZOOM_TO_LEVEL = [8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 5, 4, 3, 2, 2, 1, 1];
window.TILE_PARAMS = {};
if (niantic_params.ZOOM_TO_LEVEL && niantic_params.TILES_PER_EDGE) {
ZOOM_TO_LEVEL = niantic_params.ZOOM_TO_LEVEL;
ZOOM_TO_TILES_PER_EDGE = niantic_params.TILES_PER_EDGE;
window.TILE_PARAMS.ZOOM_TO_LEVEL = niantic_params.ZOOM_TO_LEVEL;
window.TILE_PARAMS.TILES_PER_EDGE = niantic_params.TILES_PER_EDGE;
// lazy numerical array comparison
if ( JSON.stringify(niantic_params.ZOOM_TO_LEVEL) != JSON.stringify(DEFAULT_ZOOM_TO_LEVEL)) {
console.warn('Tile parameter ZOOM_TO_LEVEL have changed in stock intel. Detectec correct values, but code should be updated');
debugger;
}
if ( JSON.stringify(niantic_params.TILES_PER_EDGE) != JSON.stringify(DEFAULT_ZOOM_TO_TILES_PER_EDGE)) {
console.warn('Tile parameter ZOOM_TO_LEVEL have changed in stock intel. Detectec correct values, but code should be updated');
debugger;
}
} else {
console.warn('Failed to detect both ZOOM_TO_LEVEL and TILES_PER_EDGE in the stock intel site - using internal defaults');
debugger;
window.TILE_PARAMS.ZOOM_TO_LEVEL = DEFAULT_ZOOM_TO_LEVEL;
window.TILE_PARAMS.TILES_PER_EDGE = DEFAULT_ZOOM_TO_TILES_PER_EDGE;
}
// the current API allows the client to request a minimum portal level. the ZOOM_TO_LEVEL list are minimums
// disable SHOW_MORE_PORTALS if it would be unfriendly to the servers (i.e. result in more requests)
// needs to be fired a bit later, after plugins have been initialised
setTimeout(function(){
if (window.CONFIG_ZOOM_SHOW_MORE_PORTALS) {
if (window.TILE_PARAMS.TILES_PER_EDGE[17] > window.TILE_PARAMS.TILES_PER_EDGE[15]) {
var edgeScale = window.TILE_PARAMS.TILES_PER_EDGE[17]/window.TILE_PARAMS.TILES_PER_EDGE[15];
var mapScale = edgeScale*edgeScale;
dialog({
title: 'Show more portals plugin disabled',
width: 400,
text: 'The "show-more-portals" plugin has been disabled.\n\n'
+'Niantic have changed the intel site so that zoom level 17 (all portals) now needs '+mapScale+' times more requests than level 15 (L1+ portals), so fetching at the wrong zoom level will be unfriendly to the servers\n\n'
+'Don\'t like this? Ask Niantic to change the standard intel site, then IITC can match and all would benifit.'
});
window.CONFIG_ZOOM_SHOW_MORE_PORTALS=false;
}
}
}, 1);
}
window.getMapZoomTileParameters = function(zoom) {
// the current API allows the client to request a minimum portal level. the window.TILE_PARAMS.ZOOM_TO_LEVEL list are minimums
// however, in my view, this can return excessive numbers of portals in many cases. let's try an optional reduction
// of detail level at some zoom levels
var level = ZOOM_TO_LEVEL[zoom] || 0; // default to level 0 (all portals) if not in array
var level = window.TILE_PARAMS.ZOOM_TO_LEVEL[zoom] || 0; // default to level 0 (all portals) if not in array
if (window.CONFIG_ZOOM_SHOW_LESS_PORTALS_ZOOMED_OUT) {
if (level <= 7 && level >= 4) {
// reduce portal detail level by one - helps reduce clutter
level = level+1;
}
}
var maxTilesPerEdge = window.TILE_PARAMS.TILES_PER_EDGE[window.TILE_PARAMS.TILES_PER_EDGE.length-1];
return {
level: level,
maxLevel: ZOOM_TO_LEVEL[zoom] || 0, // for reference, for log purposes, etc
tilesPerEdge: ZOOM_TO_TILES_PER_EDGE[zoom] || MAX_TILES_PER_EDGE,
maxLevel: window.TILE_PARAMS.ZOOM_TO_LEVEL[zoom] || 0, // for reference, for log purposes, etc
tilesPerEdge: window.TILE_PARAMS.TILES_PER_EDGE[zoom] || maxTilesPerEdge,
zoom: zoom // include the zoom level, for reference
};
}
@ -50,7 +96,7 @@ window.getMapZoomTileParameters = function(zoom) {
window.getDataZoomForMapZoom = function(zoom) {
// we can fetch data at a zoom level different to the map zoom.
//NOTE: the specifics of this are tightly coupled with the above ZOOM_TO_LEVEL and ZOOM_TO_TILES_PER_EDGE arrays
//NOTE: the specifics of this are tightly coupled with the above ZOOM_TO_LEVEL and TILES_PER_EDGE arrays
// firstly, some of IITCs zoom levels, depending on base map layer, can be higher than stock. limit zoom level
// (stock site max zoom may vary depending on google maps detail in the area - 20 or 21 max is common)
@ -66,7 +112,7 @@ window.getDataZoomForMapZoom = function(zoom) {
// to avoid impacting server load, we keep ourselves restricted to a zoom level with the sane numbre
// of tilesPerEdge and portal levels visible
while (zoom > 5) {
while (zoom > MIN_ZOOM) {
var newTileParams = getMapZoomTileParameters(zoom-1);
if (newTileParams.tilesPerEdge != origTileParams.tilesPerEdge || newTileParams.level != origTileParams.level) {
// switching to zoom-1 would result in a different detail level - so we abort changing things

View File

@ -487,6 +487,7 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
var errorTiles = [];
var retryTiles = [];
var timeoutTiles = [];
var unaccountedTiles = tiles.slice(0); // Clone
if (!success || !data || !data.result) {
console.warn('Request.handleResponse: request failed - requeuing...'+(data && data.error?' error: '+data.error:''));
@ -513,7 +514,7 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
window.runHooks('requestFinished', {success: false});
}
unaccountedTiles = [];
} else {
// TODO: use result.minLevelOfDetail ??? stock site doesn't use it yet...
@ -522,7 +523,7 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
for (var id in m) {
var val = m[id];
unaccountedTiles.splice(unaccountedTiles.indexOf(id), 1);
if ('error' in val) {
// server returned an error for this individual data tile
@ -571,6 +572,7 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
if (retryTiles.length) statusMsg += ', '+retryTiles.length+' retried';
if (timeoutTiles.length) statusMsg += ', '+timeoutTiles.length+' timed out';
if (errorTiles.length) statusMsg += ', '+errorTiles.length+' failed';
if (unaccountedTiles.length) statusMsg += ', '+unaccountedTiles.length+' unaccounted';
statusMsg += '. delay '+nextQueueDelay+' seconds';
console.log (statusMsg);
@ -602,6 +604,14 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
}
}
if (unaccountedTiles.length > 0) {
for (var i in unaccountedTiles) {
var id = unaccountedTiles[i];
delete this.requestedTiles[id];
this.requeueTile(id, true);
}
}
for (var i in successTiles) {
var id = successTiles[i];
delete this.requestedTiles[id];

View File

@ -93,11 +93,9 @@ window.getURLParam = function(param) {
// read cookie by name.
// http://stackoverflow.com/a/5639455/1684530 by cwolves
var cookies;
window.readCookie = function(name,c,C,i){
if(cookies) return cookies[name];
c = document.cookie.split('; ');
cookies = {};
window.readCookie = function(name){
var C, i, c = document.cookie.split('; ');
var cookies = {};
for(i=c.length-1; i>=0; i--){
C = c[i].split('=');
cookies[C[0]] = unescape(C[1]);
@ -106,7 +104,8 @@ window.readCookie = function(name,c,C,i){
}
window.writeCookie = function(name, val) {
document.cookie = name + "=" + val + '; expires=Thu, 31 Dec 2020 23:59:59 GMT; path=/';
var d = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000).toUTCString();
document.cookie = name + "=" + val + '; expires='+d+'; path=/';
}
window.eraseCookie = function(name) {

BIN
images/mission-length.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

16
images/missions.svg Normal file
View File

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="96" height="96">
<defs>
<mask id="mask">
<path style="stroke:#000000;stroke-width:9;stroke-linejoin:miter" d="m 28,50 8,0 6,-14 8,0" />
<circle cx="48" cy="48" r="40" style="fill:#ffffff" />
</mask>
</defs>
<g style="opacity:0.8;fill:#ffffff;stroke:#ffffff;stroke-linecap:butt;stroke-linejoin:miter">
<g mask="url(#mask)">
<path style="opacity:0.5;fill:none;stroke-width:4" transform="rotate(45,48,48)" d="m 24,8 0,80 M 48,8 48,88 M 72,8 72,88 M 8,72 88,72 M 8,48 88,48 M 8,24 88,24" />
</g>
<circle cx="50" cy="36" r="4" style="stroke:none" />
<circle cx="28" cy="50" r="4" style="stroke:none" />
<path style="fill:none;stroke-width:3" d="m 28,50 8,0 6,-14 8,0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 766 B

13
main.js
View File

@ -1,15 +1,19 @@
// ==UserScript==
// @id ingress-intel-total-conversion@jonatkins
// @name IITC: Ingress intel map total conversion
// @version 0.22.2.@@DATETIMEVERSION@@
// @version 0.22.3.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Total conversion for the ingress intel map.
// @include http://www.ingress.com/intel*
// @include https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==
@ -160,7 +164,8 @@ window.MOD_TYPE = {RES_SHIELD:'Shield', MULTIHACK:'Multi-hack', FORCE_AMP:'Force
window.ACCESS_INDICATOR_COLOR = 'orange';
window.RANGE_INDICATOR_COLOR = 'red'
// min zoom for intel map - should match that used by stock intel
window.MIN_ZOOM = 3;
window.DEFAULT_PORTAL_IMG = '//commondatastorage.googleapis.com/ingress.com/img/default-portal-image.png';
//window.NOMINATIM = '//nominatim.openstreetmap.org/search?format=json&limit=1&q=';

View File

@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cradle.iitc_mobile"
android:installLocation="auto"
android:versionCode="95"
android:versionName="0.22.2">
android:versionCode="96"
android:versionName="0.22.3">
<uses-sdk
android:minSdkVersion="14"
@ -60,6 +60,14 @@
android:host="www.ingress.com"
android:pathPrefix="/intel"
android:scheme="http"/>
<data
android:host="www.ingress.com"
android:pathPrefix="/mission/"
android:scheme="https"/>
<data
android:host="www.ingress.com"
android:pathPrefix="/mission/"
android:scheme="http"/>
</intent-filter>
<!-- Handles geo: URIs -->

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

Binary file not shown.

After

Width:  |  Height:  |  Size: 1015 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:textSize="18sp"/>
<EditText
android:id="@+id/value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dip"
android:inputType="text"
android:scrollHorizontally="true"
android:selectAllOnFocus="true"/>
</LinearLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Title for a JavaScript dialog. "The page at <url of current page> says:" -->
<string name="js_dialog_title">The page at \"%s\" says:</string>
<!-- Default title for a javascript dialog -->
<string name="js_dialog_title_default">JavaScript</string>
<!-- Title for the unload javascript dialog -->
<string name="js_dialog_before_unload_title">Confirm Navigation</string>
<!-- Text for the positive button on the unload javascript dialog -->
<string name="js_dialog_before_unload_positive_button">Leave this Page</string>
<!-- Text for the negative button on the unload javascript dialog -->
<string name="js_dialog_before_unload_negative_button">Stay on this Page</string>
<!-- Message in a javascript dialog asking if the user wishes to leave the current page -->
<string name="js_dialog_before_unload">%s\n\nAre you sure you want to navigate away from this page?</string>
</resources>

View File

@ -0,0 +1,154 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// package android.webkit;
package com.cradle.iitc_mobile;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.URLUtil;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.TextView;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Helper class to create JavaScript dialogs. It is used by
* different WebView implementations.
*
* @hide Helper class for internal use
*/
public class IITC_JsDialogHelper {
// Dialog types
public static final int ALERT = 1;
public static final int CONFIRM = 2;
public static final int PROMPT = 3;
public static final int UNLOAD = 4;
private final String mDefaultValue;
private final JsResult mResult;
private final String mMessage;
private final int mType;
private final String mUrl;
public IITC_JsDialogHelper(final int type, final WebView view, final String url,
final String message, final String defaultValue, final JsResult result) {
mResult = result;
mDefaultValue = defaultValue;
mMessage = message;
mType = type;
mUrl = url;
showDialog(view.getContext());
}
@SuppressLint("InflateParams")
private void showDialog(final Context context) {
String title, displayMessage;
int positiveTextId, negativeTextId;
if (mType == UNLOAD) {
title = context.getString(R.string.js_dialog_before_unload_title);
displayMessage = context.getString(
R.string.js_dialog_before_unload, mMessage);
positiveTextId = R.string.js_dialog_before_unload_positive_button;
negativeTextId = R.string.js_dialog_before_unload_negative_button;
} else {
title = getJsDialogTitle(context);
displayMessage = mMessage;
positiveTextId = android.R.string.ok;
negativeTextId = android.R.string.cancel;
}
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title);
builder.setOnCancelListener(new CancelListener());
if (mType != PROMPT) {
builder.setMessage(displayMessage);
builder.setPositiveButton(positiveTextId, new PositiveListener(null));
} else {
final View view = LayoutInflater.from(context).inflate(
R.layout.js_prompt, null);
final EditText edit = ((EditText) view.findViewById(R.id.value));
edit.setText(mDefaultValue);
builder.setPositiveButton(positiveTextId, new PositiveListener(edit));
((TextView) view.findViewById(R.id.message)).setText(mMessage);
builder.setView(view);
}
if (mType != ALERT) {
builder.setNegativeButton(negativeTextId, new CancelListener());
}
builder.show();
}
private class CancelListener implements DialogInterface.OnCancelListener,
DialogInterface.OnClickListener {
@Override
public void onCancel(final DialogInterface dialog) {
mResult.cancel();
}
@Override
public void onClick(final DialogInterface dialog, final int which) {
mResult.cancel();
}
}
private class PositiveListener implements DialogInterface.OnClickListener {
private final EditText mEdit;
public PositiveListener(final EditText edit) {
mEdit = edit;
}
@Override
public void onClick(final DialogInterface dialog, final int which) {
if (mEdit == null) {
mResult.confirm();
} else {
((JsPromptResult) mResult).confirm(mEdit.getText().toString());
}
}
}
private String getJsDialogTitle(final Context context) {
String title = mUrl;
if (URLUtil.isDataUrl(mUrl)) {
// For data: urls, we just display 'JavaScript' similar to Chrome.
title = context.getString(R.string.js_dialog_title_default);
} else {
try {
final URL alertUrl = new URL(mUrl);
// For example: "The page at 'http://www.mit.edu' says:"
title = context.getString(R.string.js_dialog_title,
alertUrl.getProtocol() + "://" + alertUrl.getHost());
} catch (final MalformedURLException ex) {
// do nothing. just use the url as the title
}
}
return title;
}
public boolean shouldInterrupt() {
return true;
}
}

View File

@ -837,7 +837,7 @@ public class IITC_Mobile extends Activity
final String js = "(function(obj){var result;" +
"console.log('>>> ' + obj.code);" +
"try{result=eval(obj.code);}catch(e){if(e.stack) console.error(e.stack);throw e;}" +
"if(result!==undefined) console.log(result.toString());" +
"if(result!==undefined) console.log(result===null?null:result.toString());" +
"})(" + obj.toString() + ");";
mIitcWebView.loadJS(js);

View File

@ -2,6 +2,8 @@ package com.cradle.iitc_mobile;
import android.webkit.ConsoleMessage;
import android.webkit.GeolocationPermissions;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
@ -52,4 +54,26 @@ public class IITC_WebChromeClient extends WebChromeClient {
return super.onConsoleMessage(message);
}
@Override
public boolean onJsAlert(final WebView view, final String url, final String message, final JsResult result) {
return new IITC_JsDialogHelper(IITC_JsDialogHelper.ALERT, view, url, message, null, result).shouldInterrupt();
}
@Override
public boolean onJsBeforeUnload(final WebView view, final String url, final String message, final JsResult result) {
return new IITC_JsDialogHelper(IITC_JsDialogHelper.UNLOAD, view, url, message, null, result).shouldInterrupt();
}
@Override
public boolean onJsConfirm(final WebView view, final String url, final String message, final JsResult result) {
return new IITC_JsDialogHelper(IITC_JsDialogHelper.CONFIRM, view, url, message, null, result).shouldInterrupt();
}
@Override
public boolean onJsPrompt(final WebView view, final String url, final String message, final String defaultValue,
final JsPromptResult result) {
return new IITC_JsDialogHelper(IITC_JsDialogHelper.PROMPT, view, url, message, defaultValue, result)
.shouldInterrupt();
}
}

View File

@ -168,6 +168,7 @@ public class IITC_WebView extends WebView {
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(final MotionEvent event) {
getHandler().removeCallbacks(mNavHider);

View File

@ -33,6 +33,14 @@ public class IITC_WebViewClient extends WebViewClient {
"body, #dashboard_container, #map_canvas { background: #000 !important; }"
.getBytes());
public static final boolean isIntelUrl(String url) {
return
url.startsWith("http://www.ingress.com/intel") ||
url.startsWith("https://www.ingress.com/intel") ||
url.startsWith("http://www.ingress.com/mission/") ||
url.startsWith("https://www.ingress.com/mission/");
}
private final IITC_Mobile mIitc;
private boolean mIitcInjected = false;
private final String mIitcPath;
@ -119,8 +127,7 @@ public class IITC_WebViewClient extends WebViewClient {
@Override
public void onPageFinished(final WebView view, final String url) {
if (url.startsWith("http://www.ingress.com/intel")
|| url.startsWith("https://www.ingress.com/intel")) {
if(isIntelUrl(url)) {
if (mIitcInjected) return;
Log.d("injecting iitc..");
loadScripts((IITC_WebView) view);
@ -229,7 +236,7 @@ public class IITC_WebViewClient extends WebViewClient {
Log.d("Google login");
return false;
}
else if (url.contains("ingress.com/intel")) {
else if (isIntelUrl(url)) {
Log.d("intel link requested, reset app and load " + url);
mIitc.reset();
mIitc.setLoadingState(true);

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -9,5 +9,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==
@ -810,7 +814,6 @@
if(latlngs.length >= 2 && latlngs.length <= 3) {
// TODO: add an API to draw-tools rather than assuming things about its internals
window.plugin.drawTools.setOptions();
var layer, layerType;
if(latlngs.length == 2) {

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant unsafeWindow
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -1,14 +1,14 @@
#portal-distance {
text-align: center;
}
#portal-distance-bearing {
.portal-distance-bearing {
display: inline-block;
vertical-align: top;
position: relative;
height: 1em;
width: 1em;
}
#portal-distance-bearing:before, #portal-distance-bearing:after {
.portal-distance-bearing:before, .portal-distance-bearing:after {
border-color: transparent currentcolor transparent transparent;
border-style: solid;
border-width: 0.75em 0.4em 0 0;
@ -22,7 +22,7 @@
-moz-transform: skewY(-30deg);
-webkit-transform: skewY(-30deg);
}
#portal-distance-bearing:after {
.portal-distance-bearing:after {
left: auto;
right: 0.15em;
transform: scaleX(-1) skewY(-30deg);

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==
@ -67,7 +71,7 @@ window.plugin.distanceToPortal.updateDistance = function() {
$('#portal-distance')
.text('Distance: ' + dist + ' ')
.append($('<span>')
.attr('id', 'portal-distance-bearing')
.addClass('portal-distance-bearing')
.css({
'transform': 'rotate('+bearing+'deg)',
'-moz-transform': 'rotate('+bearing+'deg)',
@ -115,7 +119,6 @@ window.plugin.distanceToPortal.setupPortalsList = function() {
$(cell).addClass('alignR').text(dist?window.plugin.distanceToPortal.formatDistance(dist):'-');
}
});
}

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -10,6 +10,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -6,11 +6,15 @@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Force https access for ingress.com/intel. If the intel site is accessed via http, it redirects to the https version.
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Force https access for the intel map. If the intel map is accessed via http, it redirects to the https version.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -10,6 +10,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

162
plugins/missions.css Normal file
View File

@ -0,0 +1,162 @@
.plugin-mission-pane {
background: transparent;
border: 0 none !important;
height: 100% !important;
width: 100% !important;
left: 0 !important;
top: 0 !important;
position: absolute;
overflow: auto;
}
.plugin-mission-summary {
padding: 5px;
border-top: black solid 1px;
min-height: 50px;
position: relative;
clear: left;
}
.plugin-mission-summary.checked::after {
content: "✓";
display: block;
pointer-events: none;
position: absolute;
text-align: center;
color: rgba(255, 187, 0, 0.3);
left: 5px;
top: 5px;
font-size: 50px;
line-height: 50px;
width: 50px;
}
.plugin-mission-summary:first-child {
border-top-width: 0px;
}
.plugin-mission-summary.checked {
background-color: rgba(255, 187, 0, 0.3);
}
.plugin-mission-summary > img {
float: left;
cursor: pointer;
width: 50px;
margin-right: 10px;
margin-bottom: 5px;
}
.plugin-mission-summary > a {
display: block;
font-weight: bold;
font-size: 1.3em;
margin: 0 0 2px 60px;
}
.plugin-mission-summary > br {
margin-bottom: 2px;
}
.plugin-mission-summary > .nickname {
display: inline-block;
box-sizing: border-box;
min-width: 8em; /* to align with time */
padding-right: 0.2em;
}
.plugin-mission-info .portal-distance-bearing {
font-size: 14px;
margin-right: 8px;
color: #b2fbff;
}
.plugin-mission-info {
display: inline-block;
}
.plugin-mission-info.length { min-width: 6em; }
.plugin-mission-info.distance { min-width: 6em; }
.plugin-mission-info.time { min-width: 8em; }
.plugin-mission-info.rating { min-width: 6em; }
.plugin-mission-info.players { min-width: 4em; }
.plugin-mission-info.type { min-width: 4em; }
.plugin-mission-info img {
height: 14px;
margin-right: 8px;
vertical-align: top;
}
.plugin-mission-info.players img {
padding: 0 3px; /* the icon is 12x18 */
}
.plugin-mission-details .plugin-mission-summary > a,
.plugin-mission-details .plugin-mission-summary .description {
white-space: pre-line;
margin-left: 110px;
}
.plugin-mission-details .plugin-mission-summary.checked::after {
left: 0px;
top: 0px;
font-size: 100px;
line-height: 100px;
width: 100px;
}
.plugin-mission-details .plugin-mission-summary {
padding: 0;
background-color: transparent;
}
.plugin-mission-details .plugin-mission-summary > img {
width: 100px;
}
.plugin-mission-details ol {
clear: left;
list-style: none;
margin: 10px 0 0;
padding: 0;
}
.plugin-mission-portal-indicator {
position: relative;
text-align: center;
float: left;
line-height: 18px;
height: 18px;
width: 18px;
margin-right: 5px;
}
.plugin-mission-portal-indicator div {
border-color: currentcolor transparent transparent;
border-style: solid;
border-width: 2px 1px;
box-sizing: border-box;
height: 0;
left: 6px;
position: absolute;
top: 0;
/* Firefox supports transform* without vendor prefix, but Android does not yet */
transform-origin: 4px 9px 0;
-webkit-transform-origin: 4px 9px 0;
width: 8px;
}
.plugin-mission-waypoint.unavailable {
text-decoration: line-through;
}
.plugin-mission-waypoint .title {
font-size: 18px;
font-weight: bold;
}
.plugin-mission-waypoint label {
clear: left;
display: block;
}
.plugin-mission-waypoint input {
box-sizing: border-box;
margin: 3px 5px 8px 0;
width: 18px;
}

View File

@ -2,15 +2,19 @@
// @id iitc-plugin-missions@jonatkins
// @name IITC plugin: Missions
// @category Info
// @version 0.0.1.@@DATETIMEVERSION@@
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] WORK IN PROGRESS: view missions. Currently, only adds a mission start portal highlighter
// @description [@@BUILDNAME@@-@@BUILDDATE@@] View missions. Marking progress on waypoints/missions basis. Showing mission paths on the map.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==
@ -19,32 +23,958 @@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.missions = function() {};
var decodeWaypoint = function(data) {
var result = {
hidden: data[0],
guid: data[1],
title: data[2],
typeNum: data[3],
type: [null, 'Portal', 'Field Trip'][data[3]],
objectiveNum: data[4],
objective: [null, 'Hack this Portal', 'Capture or Upgrade Portal', 'Create Link from Portal', 'Create Field from Portal', 'Install a Mod on this Portal', 'Take a Photo', 'View this Field Trip Waypoint', 'Enter the Passphrase'][data[4]],
};
if (result.typeNum === 1 && data[5]) {
result.portal = window.decodeArray.portalSummary(data[5]);
// Portal waypoints have the same guid as the respective portal.
result.portal.guid = result.guid;
}
return result;
};
var decodeMission = function(data) {
return {
guid: data[0],
title: data[1],
description: data[2],
authorNickname: data[3],
authorTeam: data[4],
// Notice: this format is weird(100%: 1.000.000)
ratingE6: data[5],
medianCompletionTimeMs: data[6],
numUniqueCompletedPlayers: data[7],
typeNum: data[8],
type: [null, 'Sequential', 'Non Sequential', 'Hidden'][data[8]],
waypoints: data[9].map(decodeWaypoint),
image: data[10]
};
};
var decodeMissionSummary = function(data) {
return {
guid: data[0],
title: data[1],
image: data[2],
ratingE6: data[3],
medianCompletionTimeMs: data[4]
};
};
var timeToRemaining = function(t) {
var data = parseInt(t / 86400) + 'd ' + (new Date(t % 86400 * 1000)).toUTCString().replace(/.*(\d{2}):(\d{2}):(\d{2}).*/, '$1h $2m $3s');
data = data.replace('0d', '');
data = data.replace('00h', '');
data = data.replace('00m', '');
return data.trim();
};
window.plugin.missions = {
// 3 days.
missionCacheTime: 3 * 24 * 3600 * 1E3,
// 3 weeks.
portalMissionsCacheTime: 21 * 24 * 3600 * 1E3,
SYNC_DELAY: 5000,
enableSync: false,
window.plugin.missions.highlight = function(data) {
var opacity = 0.7;
var color = undefined;
missionTypeImages: [
'@@INCLUDEIMAGE:images/mission-type-unknown.png@@',
'@@INCLUDEIMAGE:images/mission-type-sequential.png@@',
'@@INCLUDEIMAGE:images/mission-type-random.png@@',
'@@INCLUDEIMAGE:images/mission-type-hidden.png@@',
],
if (data.portal.options.data.mission50plus) {
color='red';
} else if (data.portal.options.data.mission) {
color='darkorange';
}
onPortalSelected: function(event) {
/*if(event.selectedPortalGuid === event.unselectedPortalGuid) {
return;
}*/
if (window.selectedPortal === null) {
return;
}
var portal = window.portals[window.selectedPortal];
if (!portal || (!portal.options.data.mission && !portal.options.data.mission50plus)) {
return;
}
// After select.
setTimeout(function() {
// #resodetails
$('.linkdetails').append('<aside><a tabindex="0" onclick="plugin.missions.openPortalMissions();" >Missions</a></aside>');
}, 0);
},
if (color) {
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
}
openTopMissions: function(bounds) {
bounds = bounds || window.map.getBounds();
this.loadMissionsInBounds(bounds, this.showMissionListDialog.bind(this));
},
window.plugin.missions.setup = function() {
openPortalMissions: function() {
var me = this,
portal = window.portals[window.selectedPortal];
if (!portal) {
return;
}
this.loadPortalMissions(window.selectedPortal, function(missions) {
if (!missions.length) {
return;
}
window.addPortalHighlighter('Mission start point', window.plugin.missions.highlight);
if (missions.length === 1) {
me.loadMission(missions[0].guid, me.showMissionDialog.bind(me));
} else {
me.showMissionListDialog(missions);
}
});
},
openMission: function(guid) {
this.loadMission(guid, this.showMissionDialog.bind(this));
},
showMissionDialog: function(mission) {
var me = this;
var markers = this.highlightMissionPortals(mission);
var content = this.renderMission(mission);
var id = mission.guid.replace(/\./g, '_'); // dots irritate the dialog framework and are not allowed in HTML IDs
if(useAndroidPanes()) {
if(this.tabHeaders[id]) {
this.tabHeaders[id].parentNode.querySelector('.ui-icon-close').click();
}
var li = this.tabBar.appendChild(document.createElement('li'));
var a = li.appendChild(document.createElement('a'));
a.textContent = mission.title;
a.href = '#mission_pane_'+id;
this.tabHeaders[id] = a;
var span = li.appendChild(document.createElement('span'));
span.className = 'ui-icon ui-icon-close';
span.textContent = 'Close mission';
span.addEventListener('click', function() {
this.unhighlightMissionPortals(markers);
li.parentNode.removeChild(li);
content.parentNode.removeChild(content);
delete this.tabHeaders[id];
$(this.tabs)
.tabs('refresh')
.find('.ui-tabs-nav')
.sortable('refresh');
}.bind(this), false);
this.tabs.appendChild(content);
content.id = 'mission_pane_'+id;
var tabs = $(this.tabs);
tabs.tabs('refresh');
tabs.find('.ui-tabs-nav').sortable('refresh');
tabs.tabs('option','active', -1);
if(window.isSmartphone())
show('plugin-missions');
} else {
dialog({
id: 'plugin-mission-details-' + id,
title: mission.title,
height: 'auto',
html: content,
width: '450px',
closeCallback: function() {
me.unhighlightMissionPortals(markers);
},
collapseCallback: this.collapseFix,
expandCallback: this.collapseFix,
}).dialog('option', 'buttons', {
'Zoom to mission': function() {
me.zoomToMission(mission);
},
'OK': function() { $(this).dialog('close'); },
});
}
},
showMissionListDialog: function(missions) {
dialog({
html: this.renderMissionList(missions),
height: 'auto',
width: '400px',
collapseCallback: this.collapseFix,
expandCallback: this.collapseFix,
}).dialog('option', 'buttons', {
'Create new mission': function() { open('//mission-author-dot-betaspike.appspot.com'); },
'OK': function() { $(this).dialog('close'); },
});
},
collapseFix: function() {
if (this && this.parentNode) {
this.parentNode.style.height = 'auto';
}
},
zoomToMission: function(mission) {
var latlngs = mission.waypoints.filter(function(waypoint) {
return !!waypoint.portal;
}).map(function(waypoint) {
return [waypoint.portal.latE6/1E6, waypoint.portal.lngE6/1E6];
});
map.fitBounds(L.latLngBounds(latlngs), {maxZoom: 17});
},
loadMissionsInBounds: function(bounds, callback, errorcallback) {
var me = this;
window.postAjax('getTopMissionsInBounds', {
northE6: ((bounds.getNorth() * 1000000) | 0),
southE6: ((bounds.getSouth() * 1000000) | 0),
westE6: ((bounds.getWest() * 1000000) | 0),
eastE6: ((bounds.getEast() * 1000000) | 0)
}, function(data) {
var missions = data.result.map(decodeMissionSummary);
if (!missions) {
if (errorcallback) {
errorcallback('Invalid data');
}
return;
}
callback(missions);
}, function(error) {
console.log('Error loading missions in bounds', arguments);
if (errorcallback) {
errorcallback(error);
}
});
},
loadPortalMissions: function(guid, callback, errorcallback) {
var me = this;
// Mission summary rarely goes stale.
if (me.cacheByPortalGuid[guid] && this.cacheByPortalGuid[guid].time > (Date.now() - this.portalMissionsCacheTime)) {
callback(me.cacheByPortalGuid[guid].data);
return;
}
window.postAjax('getTopMissionsForPortal', {
guid: window.selectedPortal
}, function(data) {
var missions = data.result.map(decodeMissionSummary);
if (!missions) {
if (errorcallback) {
errorcallback('Invalid data');
}
return;
}
window.runHooks('plugin-missions-on-portal-loaded', { missions: missions, portalguid: guid });
me.cacheByPortalGuid[guid] = {
time: Date.now(),
data: missions
};
me.storeCache();
callback(missions);
}, function(error) {
console.log('Error loading portal missions', arguments);
if (errorcallback) {
errorcallback(error);
}
// awww
});
},
loadMission: function(guid, callback, errorcallback) {
var me = this;
// TODO: we need to refresh data often enough, portal data can quickly go stale
if (this.cacheByMissionGuid[guid] && this.cacheByMissionGuid[guid].time > (Date.now() - this.missionCacheTime)) {
callback(this.getMissionCache(guid, true));
return;
}
window.postAjax('getMissionDetails', {
guid: guid
}, function(data) {
var mission = decodeMission(data.result);
if (!mission) {
if (errorcallback) {
errorcallback('Invalid data');
}
return;
}
window.runHooks('plugin-missions-loaded-mission', { mission: mission });
me.cacheByMissionGuid[guid] = {
time: Date.now(),
data: mission
};
me.storeCache();
callback(mission);
}, function() {
console.error('Error loading mission data: ' + guid + ', ' + Array.prototype.slice.call(arguments));
if (errorcallback) {
errorcallback(error);
}
// awww
});
},
renderMissionList: function(missions) {
var container = document.createElement('div');
missions.forEach(function(mission) {
container.appendChild(this.renderMissionSummary(mission));
}, this);
return container;
},
renderMissionSummary: function(mission) {
var cachedMission = this.getMissionCache(mission.guid);
var checked = this.checkedMissions[mission.guid];
var container = document.createElement('div');
container.className = 'plugin-mission-summary';
container.dataset['mission_mid'] = mission.guid;
if(checked)
container.classList.add('checked');
var img = container.appendChild(document.createElement('img'));
img.src = mission.image;
img.addEventListener('click', function(ev) {
plugin.missions.toggleMission(mission.guid);
}, false);
var title = container.appendChild(document.createElement('a'));
title.textContent = mission.title;
title.href = '/mission/' + mission.guid;
title.addEventListener('click', function(ev) {
this.openMission(mission.guid);
// prevent browser from following link
ev.preventDefault();
return false;
}.bind(this), false);
if(cachedMission) {
var span = container.appendChild(document.createElement('span'));
span.className = 'nickname ' + (cachedMission.authorTeam === 'R' ? 'res' : 'enl')
span.textContent = cachedMission.authorNickname;
var len = cachedMission.waypoints.filter(function(waypoint) {
return !!waypoint.portal;
}).map(function(waypoint) {
return L.latLng(waypoint.portal.latE6/1E6, waypoint.portal.lngE6/1E6);
}).map(function(latlng1, i, latlngs) {
if(i == 0) return 0;
var latlng2 = latlngs[i - 1];
return latlng1.distanceTo(latlng2);
}).reduce(function(a, b) {
return a + b;
});
if(len > 0) {
if(len > 1000)
len = Math.round(len / 100) / 10 + 'km';
else
len = Math.round(len * 10) / 10 + 'm';
var infoLength = container.appendChild(document.createElement('span'));
infoLength.className = 'plugin-mission-info length help';
infoLength.title = 'Length of this mission.\n\nNOTE: The actual distance required to cover may vary depending on several factors!';
infoLength.textContent = len;
img = infoLength.insertBefore(document.createElement('img'), infoLength.firstChild);
img.src = '@@INCLUDEIMAGE:images/mission-length.png@@';
}
if(window.plugin.distanceToPortal && window.plugin.distanceToPortal.currentLoc) {
var infoDistance = container.appendChild(document.createElement('span'));
infoDistance.className = 'plugin-mission-info distance help';
infoDistance.title = 'Distance to this mission. Click to update.';
infoDistance.addEventListener('click', function() {
plugin.missions.renderMissionDistance(cachedMission, infoDistance);
}, false);
this.renderMissionDistance(cachedMission, infoDistance);
}
}
container.appendChild(document.createElement('br'));
var infoTime = container.appendChild(document.createElement('span'));
infoTime.className = 'plugin-mission-info time help';
infoTime.title = 'Typical duration';
infoTime.textContent = timeToRemaining((mission.medianCompletionTimeMs / 1000) | 0) + ' ';
img = infoTime.insertBefore(document.createElement('img'), infoTime.firstChild);
img.src = 'https://commondatastorage.googleapis.com/ingress.com/img/tm_icons/time.png';
var infoRating = container.appendChild(document.createElement('span'));
infoRating.className = 'plugin-mission-info rating help';
infoRating.title = 'Average rating';
infoRating.textContent = (((mission.ratingE6 / 100) | 0) / 100) + '%' + ' ';
img = infoRating.insertBefore(document.createElement('img'), infoRating.firstChild);
img.src = 'https://commondatastorage.googleapis.com/ingress.com/img/tm_icons/like.png';
if (cachedMission) {
var infoPlayers = container.appendChild(document.createElement('span'));
infoPlayers.className = 'plugin-mission-info players help';
infoPlayers.title = 'Unique players who have completed this mission';
infoPlayers.textContent = cachedMission.numUniqueCompletedPlayers + ' ';
img = infoPlayers.insertBefore(document.createElement('img'), infoPlayers.firstChild);
img.src = 'https://commondatastorage.googleapis.com/ingress.com/img/tm_icons/players.png';
var infoWaypoints = container.appendChild(document.createElement('span'));
infoWaypoints.className = 'plugin-mission-info waypoints help';
infoWaypoints.title = (cachedMission.type ? cachedMission.type + ' mission' : 'Unknown mission type')
+ ' with ' + cachedMission.waypoints.length + ' waypoints';
infoWaypoints.textContent = cachedMission.waypoints.length + ' ';
img = infoWaypoints.insertBefore(document.createElement('img'), infoWaypoints.firstChild);
img.src = this.missionTypeImages[cachedMission.typeNum] || this.missionTypeImages[0];
}
return container;
},
renderMissionDistance: function(mission /* cached mission, full details*/, container) {
if(!(plugin.distanceToPortal && plugin.distanceToPortal.currentLoc)) return;
var distances = mission.waypoints
.filter(function(waypoint) {
return !!waypoint.portal;
})
.map(function(waypoint) {
var position = L.latLng(waypoint.portal.latE6/1E6, waypoint.portal.lngE6/1E6);
var distance = position.distanceTo(plugin.distanceToPortal.currentLoc);
return {
waypoint: waypoint,
distance: distance,
position: position,
};
});
if(!distances.length) return;
if(mission.typeNum == 2) { // non-sequential
distances.sort(function(a, b) { return a.distance - b.distance; });
}
var position = distances[0].position;
var distance = distances[0].distance;
var bearing = window.plugin.distanceToPortal.currentLoc.bearingTo(position);
$(container)
.text(window.plugin.distanceToPortal.formatDistance(distance))
.prepend($('<span>')
.addClass('portal-distance-bearing')
.css({
'transform': 'rotate('+bearing+'deg)',
'-moz-transform': 'rotate('+bearing+'deg)',
'-webkit-transform': 'rotate('+bearing+'deg)',
}));
},
renderMission: function(mission) {
var container = document.createElement('div');
container.className = 'plugin-mission-details';
var summary = container.appendChild(this.renderMissionSummary(mission));
var desc = summary.appendChild(document.createElement('p'));
desc.className = 'description';
desc.textContent = mission.description;
var list = container.appendChild(document.createElement('ol'))
mission.waypoints.forEach(function(waypoint, index) {
list.appendChild(this.renderMissionWaypoint(waypoint, index, mission));
}, this);
return container;
},
renderMissionWaypoint: function(waypoint, index, mission) {
var container = document.createElement('li');
container.className = 'plugin-mission-waypoint';
if (waypoint.portal) {
container.appendChild(this.renderPortalCircle(waypoint.portal));
var title = container.appendChild(document.createElement('a'));
var lat = waypoint.portal.latE6/1E6;
var lng = waypoint.portal.lngE6/1E6;
var perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng;
title.href = perma;
title.addEventListener('click', function(ev) {
if(window.isSmartphone())
show('map');
selectPortalByLatLng(lat, lng);
ev.preventDefault();
return false;
}, false);
title.addEventListener('dblclick', function(ev) {
if(window.isSmartphone())
show('map');
zoomToAndShowPortal(waypoint.portal.guid, [lat, lng]);
ev.preventDefault();
return false;
}, false);
} else if(waypoint.typeNum === 1) {
// if typeNum === 1 but portal is undefined, this waypoint is a deleted portal.
var title = container.appendChild(document.createElement('span'));
container.classList.add('unavailable');
} else {
var title = container.appendChild(document.createElement('span'));
}
title.className = 'title';
if(waypoint.title)
title.textContent = waypoint.title;
else if(waypoint.portal && waypoint.portal.title)
title.textContent = waypoint.portal.title;
else
title.textContent = 'Unknown';
var mwpid = mission.guid + '-' + index + '-' + waypoint.guid;
var checked = this.checkedWaypoints[mwpid];
var label = container.appendChild(document.createElement('label'));
var checkbox = label.appendChild(document.createElement('input'));
checkbox.type = 'checkbox';
checkbox.addEventListener('change', function() {
plugin.missions.toggleWaypoint(mission.guid, mwpid);
}, false);
checkbox.dataset['mission_mwpid'] = mwpid;
var objective = label.appendChild(document.createElement('span'));
objective.textContent = waypoint.objective ? waypoint.objective : '?';
return container;
},
renderPortalCircle: function(portal) {
var team = TEAM_TO_CSS[getTeam(portal)];
var resCount = portal.resCount;
var level = resCount == 0 ? 0 : portal.level; // we want neutral portals to be level 0
var container = document.createElement('div');
container.className = 'plugin-mission-portal-indicator help ' + team;
container.textContent = level;
container.title = 'Level:\t'+level+'\nResonators:\t'+resCount+'\nHealth:\t'+portal.health+'%';
for(var i = 0; i< resCount; i++) {
var resonator = container.appendChild(document.createElement('div'));
/* Firefox supports transform* without vendor prefix, but Android does not yet */
resonator.style.transform = 'rotate(' + i*45 + 'deg)';
resonator.style.webkitTransform = 'rotate(' + i*45 + 'deg)';
}
return container;
},
toggleWaypoint: function(mid, mwpid, dontsave) {
if(this.checkedWaypoints[mwpid])
delete this.checkedWaypoints[mwpid];
else
this.checkedWaypoints[mwpid] = true;
window.runHooks('plugin-missions-waypoint-changed', { mwpid: mwpid, });
if (!dontsave) {
this.checkedWaypointsUpdateQueue[mwpid] = true;
this.storeLocal('checkedWaypoints');
this.storeLocal('checkedWaypointsUpdateQueue');
this.syncQueue();
}
},
onWaypointChanged: function(data) {
var mwpid = data.mwpid;
var checked = !!this.checkedWaypoints[mwpid];
$('[data-mission_mwpid="'+mwpid+'"]').prop('checked', checked);
},
onWaypointsRefreshed: function() {
$('[data-mission_mwpid]').each(function(i, element) {
var mwpid = element.dataset['mission_mwpid'];
var checked = !!this.checkedWaypoints[mwpid];
element.checked = checked;
});
},
toggleMission: function(mid) {
if(this.checkedMissions[mid])
delete this.checkedMissions[mid];
else
this.checkedMissions[mid] = true;
window.runHooks('plugin-missions-mission-changed', { mid: mid, });
this.checkedMissionsUpdateQueue[mid] = true;
this.storeLocal('checkedMissions');
this.storeLocal('checkedMissionsUpdateQueue');
this.syncQueue();
},
onMissionChanged: function(data) {
var mid = data.mid;
var checked = !!this.checkedMissions[mid];
$('[data-mission_mid="'+mid+'"]').toggleClass('checked', checked);
},
onMissionsRefreshed: function() {
$('[data-mission_mid]').each(function(i, element) {
var mid = element.dataset['mission_mid'];
var checked = !!this.checkedMissions[mid];
$(element).toggleClass('checked', checked);
});
},
getMissionCache: function(guid, updatePortals) {
if (this.cacheByMissionGuid[guid]) {
var cache = this.cacheByMissionGuid[guid];
// Update portal data from map if older then 2 minutes.
if (updatePortals && cache.time < (Date.now() - (2 * 60 * 1000))) {
cache.data.waypoints.map(function(waypoint) {
if (!waypoint.portal) {
return;
}
var wp = window.portals[waypoint.portal.guid];
if (!wp) {
return;
}
$.extend(waypoint.portal, wp.options.data);
});
}
return cache.data;
}
return null;
},
getPortalCache: function(guid) {
if (this.cacheByPortalGuid[guid]) {
return this.cacheByPortalGuid[guid].data;
}
return null;
},
storeCache: function() {
this.checkCacheSize();
localStorage['plugins-missions-portalcache'] = JSON.stringify(this.cacheByPortalGuid);
localStorage['plugins-missions-missioncache'] = JSON.stringify(this.cacheByMissionGuid);
},
storeLocal: function(key) {
localStorage['plugins-missions-' + key] = JSON.stringify(this[key]);
},
loadData: function() {
this.cacheByPortalGuid = JSON.parse(localStorage['plugins-missions-portalcache'] || '{}');
this.cacheByMissionGuid = JSON.parse(localStorage['plugins-missions-missioncache'] || '{}');
if('plugins-missions-settings' in localStorage) {
var settings = JSON.parse(localStorage['plugins-missions-settings'] || '{}');
localStorage['plugins-missions-checkedMissions'] = JSON.stringify(settings.checkedMissions);
localStorage['plugins-missions-checkedWaypoints'] = JSON.stringify(settings.checkedWaypoints);
delete localStorage['plugins-missions-settings'];
}
this.loadLocal('checkedMissions');
this.loadLocal('checkedMissionsUpdateQueue');
this.loadLocal('checkedMissionsUpdatingQueue');
this.loadLocal('checkedWaypoints');
this.loadLocal('checkedWaypointsUpdateQueue');
this.loadLocal('checkedWaypointsUpdatingQueue');
},
loadLocal: function(key) {
this[key] = JSON.parse(localStorage['plugins-missions-' + key] || '{}');
},
checkCacheSize: function() {
if (JSON.stringify(this.cacheByPortalGuid).length > 1e6) { // 1 MB not MiB ;)
this.cleanupPortalCache();
}
if (JSON.stringify(this.cacheByMissionGuid).length > 2e6) { // 2 MB not MiB ;)
this.cleanupMissionCache();
}
},
// Cleanup oldest half of the data.
cleanupPortalCache: function() {
var me = this;
var cache = Object.keys(this.cacheByPortalGuid);
cache.sort(function(a, b) {
return me.cacheByPortalGuid[a].time - me.cacheByPortalGuid[b].time;
});
var toDelete = (cache.length / 2) | 0;
cache.splice(0, toDelete + 1).forEach(function(el) {
delete me.cacheByPortalGuid[el];
});
},
// Cleanup oldest half of the data.
cleanupMissionCache: function() {
var me = this;
var cache = Object.keys(this.cacheByMissionGuid);
cache.sort(function(a, b) {
return me.cacheByMissionGuid[a].time - me.cacheByMissionGuid[b].time;
});
var toDelete = (cache.length / 2) | 0;
cache.splice(0, toDelete + 1).forEach(function(el) {
delete me.cacheByMissionGuid[el];
});
},
highlightMissionPortals: function(mission) {
var markers = [];
var latlngs = [];
mission.waypoints.forEach(function(waypoint) {
if (!waypoint.portal) {
return;
}
var radius = window.portals[waypoint.portal.guid] ? window.portals[waypoint.portal.guid].options.radius * 1.5 : 5;
var ll = [waypoint.portal.latE6 / 1E6, waypoint.portal.lngE6 / 1E6];
latlngs.push(ll);
var marker = L.circleMarker(ll, {
radius: radius,
weight: 3,
opacity: 1,
color: '#222',
fill: false,
dashArray: null,
clickable: false
}
);
this.missionLayer.addLayer(marker);
markers.push(marker);
}, this);
var line = L.geodesicPolyline(latlngs, {
color: '#222',
opacity: 1,
weight: 2,
clickable: false,
dashArray: (mission.typeNum == 2 /* non-sequential */ ? '1,5' : undefined),
});
this.missionLayer.addLayer(line);
markers.push(line);
return markers;
},
unhighlightMissionPortals: function(markers) {
markers.forEach(function(marker) {
this.missionLayer.removeLayer(marker);
}, this);
},
onPortalChanged: function(type, guid, oldval) {
var portal;
if (type === 'add' || type === 'update') {
// Compatibility
portal = window.portals[guid] || oldval;
if (!portal.options.data.mission && !portal.options.data.mission50plus) {
return;
}
if (this.markedStarterPortals[guid]) {
return;
}
this.markedStarterPortals[guid] = L.circleMarker(
L.latLng(portal.options.data.latE6 / 1E6, portal.options.data.lngE6 / 1E6), {
radius: portal.options.radius + Math.ceil(portal.options.radius / 2),
weight: 3,
opacity: 1,
color: '#555',
fill: false,
dashArray: null,
clickable: false
}
);
this.missionStartLayer.addLayer(this.markedStarterPortals[guid]);
} else if (type === 'delete') {
portal = oldval;
if (!this.markedStarterPortals[guid]) {
return;
}
this.missionStartLayer.removeLayer(this.markedStarterPortals[guid]);
delete this.markedStarterPortals[guid];
}
},
// sync the queue, but delay the actual sync to group a few updates in a single request
syncQueue: function() {
if(!this.enableSync) return;
clearTimeout(this.syncTimer);
this.syncTimer = setTimeout(function() {
this.syncTimer = null;
$.extend(this.checkedMissionsUpdatingQueue, this.checkedMissionsUpdateQueue);
this.checkedMissionsUpdateQueue = {};
this.storeLocal('checkedMissionsUpdatingQueue');
this.storeLocal('checkedMissionsUpdateQueue');
plugin.sync.updateMap('missions', 'checkedMissions', Object.keys(this.checkedMissionsUpdatingQueue));
$.extend(this.checkedWaypointsUpdatingQueue, this.checkedWaypointsUpdateQueue);
this.checkedWaypointsUpdateQueue = {};
this.storeLocal('checkedWaypointsUpdatingQueue');
this.storeLocal('checkedWaypointsUpdateQueue');
plugin.sync.updateMap('missions', 'checkedWaypoints', Object.keys(this.checkedWaypointsUpdatingQueue));
}.bind(this), this.SYNC_DELAY);
},
// called after IITC and all plugin loaded
registerFieldForSyncing: function() {
if(!window.plugin.sync) return;
window.plugin.sync.registerMapForSync('missions', 'checkedMissions', this.syncCallback.bind(this), this.syncInitialed.bind(this));
window.plugin.sync.registerMapForSync('missions', 'checkedWaypoints', this.syncCallback.bind(this), this.syncInitialed.bind(this));
},
// called after local or remote change uploaded
syncCallback: function(pluginName, fieldName, e, fullUpdated) {
this.storeLocal(fieldName);
// All data is replaced if another client updates the data while this client was offline,
// fire a complete refresh
if(fullUpdated) {
if(fieldName === 'checkedMissions') {
window.runHooks('plugin-missions-missions-refreshed');
} else if(fieldName === 'checkedWaypoints') {
window.runHooks('plugin-missions-waypoints-refreshed');
}
return;
}
if(!e) return;
if(e.isLocal) {
// Update pushed successfully, remove it from updatingQueue
delete this[fieldName + 'UpdatingQueue'][e.property];
} else {
// Remote update
delete this[fieldName + 'UpdateQueue'][e.property]
this.storeLocal(fieldName + 'UpdateQueue');
if(fieldName === 'checkedMissions') {
window.runHooks('plugin-missions-mission-changed', { mid: e.property, });
} else if(fieldName === 'checkedWaypoints') {
window.runHooks('plugin-missions-waypoint-changed', { mwpid: e.property, });
}
}
},
// syncing of the field is initialed, upload all queued update
syncInitialed: function(pluginName, fieldName) {
this.enableSync = true;
if(Object.keys(this[fieldName + 'UpdateQueue']).length > 0) {
this.syncQueue();
}
},
onPaneChanged: function(pane) {
if(pane == 'plugin-missions') {
document.body.appendChild(this.mobilePane);
} else if(this.mobilePane.parentNode) {
this.mobilePane.parentNode.removeChild(this.mobilePane);
}
},
setup: function() {
this.cacheByPortalGuid = {};
this.cacheByMissionGuid = {};
this.markedStarterPortals = {};
this.markedMissionPortals = {};
this.loadData();
$('<style>').prop('type', 'text/css').html('@@INCLUDESTRING:plugins/missions.css@@').appendTo('head');
$('#toolbox').append('<a tabindex="0" onclick="plugin.missions.openTopMissions();">Missions in view</a>');
if(window.useAndroidPanes()) {
this.mobilePane = document.createElement('div');
this.mobilePane.className = 'plugin-mission-pane';
var button = this.mobilePane.appendChild(document.createElement('button'));
button.textContent = 'Missions in view';
button.addEventListener('click', function(){ this.openTopMissions(); }.bind(this), false);
this.tabs = this.mobilePane.appendChild(document.createElement('div'));
this.tabBar = this.tabs.appendChild(document.createElement('ul'));
this.tabHeaders = {};
$(this.tabs)
.tabs()
.find('.ui-tabs-nav').sortable({
axis: 'x',
stop: function() {
$(this.tabs).tabs('refresh');
},
});
android.addPane('plugin-missions', 'Missions', 'ic_missions');
addHook('paneChanged', this.onPaneChanged.bind(this));
}
// window.addPortalHighlighter('Mission start point', this.highlight.bind(this));
window.addHook('portalSelected', this.onPortalSelected.bind(this));
/*
I know iitc has portalAdded event but it is missing portalDeleted. So we have to resort to Object.observe
*/
var me = this;
if (Object.observe) { // Chrome
Object.observe(window.portals, function(changes) {
changes.forEach(function(change) {
me.onPortalChanged(change.type, change.name, change.oldValue);
});
});
} else { // Firefox why no Object.observer ? :<
window.addHook('portalAdded', function(data) {
me.onPortalChanged('add', data.portal.options.guid, data.portal);
});
// TODO: bug iitc dev for portalRemoved event
var oldDeletePortal = window.Render.prototype.deletePortalEntity;
window.Render.prototype.deletePortalEntity = function(guid) {
if (guid in window.portals) {
me.onPortalChanged('delete', guid, window.portals[guid]);
}
oldDeletePortal.apply(this, arguments);
};
}
this.missionStartLayer = new L.LayerGroup();
this.missionLayer = new L.LayerGroup();
window.addLayerGroup('Mission start portals', this.missionStartLayer, false);
window.addLayerGroup('Mission portals', this.missionLayer, true);
window.pluginCreateHook('plugin-missions-loaded-mission');
window.pluginCreateHook('plugin-missions-on-portal-loaded');
window.pluginCreateHook('plugin-missions-mission-changed');
window.pluginCreateHook('plugin-missions-missions-refreshed');
window.pluginCreateHook('plugin-missions-waypoint-changed');
window.pluginCreateHook('plugin-missions-waypoints-refreshed');
window.addHook('plugin-missions-mission-changed', this.onMissionChanged.bind(this));
window.addHook('plugin-missions-missions-refreshed', this.onMissionsRefreshed.bind(this));
window.addHook('plugin-missions-waypoint-changed', this.onWaypointChanged.bind(this));
window.addHook('plugin-missions-waypoints-refreshed', this.onWaypointsRefreshed.bind(this));
window.addHook('iitcLoaded', this.registerFieldForSyncing.bind(this));
var match = location.pathname.match(/\/mission\/([0-9a-z.]+)/);
if(match && match[1]) {
var mid = match[1];
this.openMission(mid);
}
}
};
var setup = window.plugin.missions.setup;
var setup = window.plugin.missions.setup.bind(window.plugin.missions);
// PLUGIN END //////////////////////////////////////////////////////////

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,4 +11,8 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,5 +11,9 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

View File

@ -11,6 +11,10 @@
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @include https://www.ingress.com/mission/*
// @include http://www.ingress.com/mission/*
// @match https://www.ingress.com/mission/*
// @match http://www.ingress.com/mission/*
// @grant none
// ==/UserScript==

Some files were not shown because too many files have changed in this diff Show More