Merge branch 'gh-pages' into scoreboard
Conflicts: plugins/README.md
12
ATTRIBUTION.md
Normal file
@ -0,0 +1,12 @@
|
||||
This project is licensed under the permissive ISC license. Parts imported from other projects remain under their respective licenses:
|
||||
|
||||
- [autolink-js by Bryan Woods; MIT](https://github.com/bryanwoods/autolink-js)
|
||||
- [load.js by Chris O'Hara; MIT](https://github.com/chriso/load.js)
|
||||
- [leaflet.js; custom license (but appears free)](http://leafletjs.com/)
|
||||
- [leaflet.draw.js; by jacobtoye; MIT](https://github.com/Leaflet/Leaflet.draw)
|
||||
- [`leaflet_google.js` by Pavel Shramov; same as Leaftlet](https://github.com/shramov/leaflet-plugins) (modified, though)
|
||||
- [jquery.qrcode.js by Jerome Etienne; MIT](https://github.com/jeromeetienne/jquery-qrcode)
|
||||
- [oms.min.js by George MacKerron; MIT](https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet)
|
||||
- [taphold.js by Rich Adams; unknown](https://github.com/richadams/jquery-taphold)
|
||||
- StackOverflow-CopyPasta is attributed in the source; [CC-Wiki](https://creativecommons.org/licenses/by-sa/3.0/)
|
||||
- all Ingress/Niantic related stuff obviously remains non-free and is still copyrighted by Niantic/Google
|
@ -27,8 +27,9 @@ Please follow the these guidelines. Some are just preference, others are good pr
|
||||
- use identity operators: `===` and `!==`. [Why do I want this?](http://stackoverflow.com/a/359509/1684530)
|
||||
- jQuery is your friend
|
||||
- indent using two spaces
|
||||
- opening brace on the same line with a space after the if/for/etc: `if(blub) {`
|
||||
- opening brace on the same line: `if(blub) {`
|
||||
- else clauses: `} else if(blub) {` or `} else {`
|
||||
- there should be no space after `if`, `for`, etc. E.g. `if(true) { doStuff(); } else { dontDoStuff(); }`
|
||||
- comments: `// this is a comment`
|
||||
- quotes: Use single-quotes for JavaScript and double-quotes for HTML content. Example: `$('body').append('<div id="soup">Soup!</div>');`.
|
||||
- there is no length limit on lines, but try to keep them short where suitable
|
||||
|
2
NEWS.md
@ -19,7 +19,7 @@ CHANGES IN 0.7 / 0.7.1
|
||||
- 0.7.1 fixes an oversight that prevented some portals from showing (by saithis)
|
||||
|
||||
### General
|
||||
- from now on there will be [nightly builds](https://www.dropbox.com/sh/lt9p0s40kt3cs6m/3xzpyiVBnF) available. You need to manually update them if you want to stay on nightly. You should be offered to update to the next release version, though. Be sure to [have read the guide on how to report bugs](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md#how-do-i-report-bugs) before using a nightly version.
|
||||
- from now on there will be [nightly builds](https://iitcserv.appspot.com/iitc-nightly/) available. You need to manually update them if you want to stay on nightly. You should be offered to update to the next release version, though. Be sure to [have read the guide on how to report bugs](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md#how-do-i-report-bugs) before using a nightly version.
|
||||
- IITC has [a shiny new user guide now](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/USERGUIDE.md). Please point new users to it, it should answer most of their questions and also teach them how to make good bug reports.
|
||||
|
||||
### Main Script
|
||||
|
109
README.md
@ -1,111 +1,4 @@
|
||||
ingress intel total conversion (IITC)
|
||||
=====================================
|
||||
|
||||
It’s annoying to extend the intel page with new features because the minified code makes it hard to grasp what’s going on. Also, one has to play catch up each time Niantic put up a new version because all the variables might get new names.
|
||||
|
||||
So instead, here’s a userscript that starts from scratch (click to zoom):
|
||||
|
||||
[](http://breunigs.github.com/ingress-intel-total-conversion/screenshots/screen.png)
|
||||
|
||||
|
||||
Features / User Guide
|
||||
---------------------
|
||||
|
||||
You already know you want it, why add a feature list here? Instead, [**read the user guide** for tricks and less obvious features](https://github.com/breunigs/ingress-intel-total-conversion/tree/gh-pages/USERGUIDE.md). If you have questions, the user guide will also likely answer them.
|
||||
|
||||
IITC can be [extended with the use of plugins](https://github.com/breunigs/ingress-intel-total-conversion/tree/gh-pages/plugins), so have a look at those if you want (or need) more.
|
||||
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Current version is 0.7.8. [See NEWS.md for details](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/NEWS.md).
|
||||
|
||||
[**INSTALL**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/dist/total-conversion-build.user.js)
|
||||
|
||||
### Firefox
|
||||
|
||||
- Install [Greasemonkey](https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/) or [Scriptish](https://addons.mozilla.org/en-US/firefox/addon/scriptish/).
|
||||
- Click install link: [install](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/dist/total-conversion-build.user.js)
|
||||
- Confirm security question.
|
||||
- Reload page.
|
||||
|
||||
*NoScript:* To make the script work whitelist at least these domains: `ingress.com github.com leafletjs.com googleapis.com`. If you want to see the cool font also whitelist `googleusercontent.com`.
|
||||
|
||||
### Chrome
|
||||
|
||||
- Install [Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo/details).
|
||||
- Click install link: [install](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/dist/total-conversion-build.user.js)
|
||||
- **Now beware:** a OK/cancel dialog pops up. It **does not** allow you to cancel the installation. Choose **OK** to install the script with Tampermonkey.
|
||||
- Confirm once again.
|
||||
- Reload page.
|
||||
|
||||
*Note:* Tampermonkey is optional. However, it offers auto-update, shows correct version numbers and installing user scripts is much easier. If you have installed the scripts directly into Chrome before, I recommend you switch to Tampermonkey. To do so, uninstall the IITC scripts and click each install link again. Follow the procedure explained above.
|
||||
|
||||
### Opera
|
||||
- Download the script: [download](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/dist/total-conversion-build.user.js)
|
||||
- put it into your user_js folder (that’s `~/.opera/user_js` on Unix). If you can’t find it [see Opera’s docs](http://www.opera.com/docs/userjs/using/#writingscripts).
|
||||
- [visit `opera:config` and check `UserJavaScriptonHTTPS` or click here to take you there](opera:config#UserPrefs|UserJavaScriptonHTTPS).
|
||||
- click save on the bottom of the settings page
|
||||
- reload the Intel Map, no need to restart Opera
|
||||
|
||||
*Note*: You need to update the scripts manually.
|
||||
|
||||
|
||||
[**INSTALL**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/dist/total-conversion-build.user.js)
|
||||
|
||||
Reporting Issues
|
||||
----------------
|
||||
|
||||
[tutorial / guide / please read / **free candy**](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md#how-do-i-report-bugs)
|
||||
|
||||
|
||||
How can I help? // Contribution
|
||||
-------------------------------
|
||||
|
||||
First of all, it’s very nice you want to help. There are several equally important ways you can. Some require a technical background and some don’t:
|
||||
- **answering help requests:** often people are asking how to do specific things in bug reports or are asking for things that already exist. Kindly point them to what they’re looking for and maybe consider updating the user guide, if it lacks on that topic.
|
||||
- **asking for more information:** Sometimes a bug report contains barely enough information to grasp what’s going on. Ask the reporter for the parts that you believe might be helpful, like the browser used. Similarily, if someone requests a feature make sure the description is accurate. Depending on the request, a concrete proposal on how to display this to the user might be helpful.
|
||||
- **finding bugs / regressions:** If you are closer to the development of IITC, it’s usually easier for you to spot misbehaviours or bugs that have been recently introduces. Opening tickets for those, ideally with a step by step guide to reproduce the issue is very helpful.
|
||||
- **hacking / sending patches:** Of course, if you want to contribute source code to the project that’s fine as well. Please [read HACKING.md for details](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md).
|
||||
|
||||
**So far, these people have contributed:**
|
||||
|
||||
[Bananeweizen](https://github.com/Bananeweizen),
|
||||
[blakjakau](https://github.com/blakjakau),
|
||||
[boombuler](https://github.com/boombuler),
|
||||
[cmrn](https://github.com/cmrn),
|
||||
[epf](https://github.com/epf),
|
||||
[Fragger](https://github.com/Fragger),
|
||||
[integ3r](https://github.com/integ3r),
|
||||
[j16sdiz](https://github.com/j16sdiz),
|
||||
[JasonMillward](https://github.com/JasonMillward),
|
||||
[jonatkins](https://github.com/jonatkins),
|
||||
[Merovius](https://github.com/Merovius),
|
||||
[mledoze](https://github.com/mledoze),
|
||||
[OshiHidra](https://github.com/OshiHidra),
|
||||
[phoenixsong6](https://github.com/phoenixsong6),
|
||||
[Pirozek](https://github.com/Pirozek),
|
||||
[saithis](https://github.com/saithis),
|
||||
[Scrool](https://github.com/Scrool),
|
||||
[sorgo](https://github.com/sorgo),
|
||||
[tpenner](https://github.com/tpenner),
|
||||
[vita10gy](https://github.com/vita10gy),
|
||||
[Xelio](https://github.com/Xelio),
|
||||
[ZauberNerd](https://github.com/ZauberNerd),
|
||||
[waynn](https://github.com/waynn)
|
||||
|
||||
|
||||
Attribution & License
|
||||
---------------------
|
||||
|
||||
This project is licensed under the permissive ISC license. Parts imported from other projects remain under their respective licenses:
|
||||
|
||||
- [autolink-js by Bryan Woods; MIT](https://github.com/bryanwoods/autolink-js)
|
||||
- [load.js by Chris O'Hara; MIT](https://github.com/chriso/load.js)
|
||||
- [leaflet.js; custom license (but appears free)](http://leafletjs.com/)
|
||||
- [leaflet.draw.js; by jacobtoye; MIT](https://github.com/Leaflet/Leaflet.draw)
|
||||
- [`leaflet_google.js` by Pavel Shramov; same as Leaftlet](https://github.com/shramov/leaflet-plugins) (modified, though)
|
||||
- [jquery.qrcode.js by Jerome Etienne; MIT](https://github.com/jeromeetienne/jquery-qrcode)
|
||||
- StackOverflow-CopyPasta is attributed in the source; [CC-Wiki](https://creativecommons.org/licenses/by-sa/3.0/)
|
||||
- all Ingress/Niantic related stuff obviously remains non-free and is still copyrighted by Niantic/Google
|
||||
# [Documentation moved to the wiki. Please see there!](https://github.com/breunigs/ingress-intel-total-conversion/wiki#head)
|
||||
|
160
USERGUIDE.md
@ -1,158 +1,4 @@
|
||||
Userguide
|
||||
=========
|
||||
USER DOCUMENTATION MOVED
|
||||
====
|
||||
|
||||
table of contents:
|
||||
- [Installation](#installation)
|
||||
- [General Usage](#general-usage)
|
||||
- [Chat](#chat)
|
||||
- [Map Display](#map-display)
|
||||
- [Map Status / Updates](#map-status--updates)
|
||||
- [Sidebar](#sidebar)
|
||||
- [Bugs and help requests](#reporting-bugs--i-need-more-help)
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
[See main README.md file for browser specific instructions](https://github.com/breunigs/ingress-intel-total-conversion#install).
|
||||
|
||||
|
||||
General Usage
|
||||
-------------
|
||||
|
||||
- many things have more information in tooltips. Let your cursor rest over stuff to show the tooltip. *Hint:* your cursor changes into a question mark / help cursor if there’s a tooltip available.
|
||||
- single left click on portals to show details.
|
||||
- double left click on portals to zoom in to them.
|
||||
|
||||
|
||||
Chat
|
||||
----
|
||||
|
||||
The chat is split up into several categories. It usually only shows messages for the current map view. It may lag behind if Niantic’s servers are slow. It also has a minimum radius of six km. This means that even if you zoom in very much, it will still show messages from a larger area around you.
|
||||
|
||||
**The chat categories are:**
|
||||
- full: shows all automated messages *(23:57 \<apj\> destroyed an L3 Resonator on Two Spikes)*
|
||||
- compact: shows only the latest automated message per user
|
||||
- public: shows user generated public messages (both Enlightened and Resistance can read it)
|
||||
- faction: shows messages for own faction (e.g. only Resistance can read Resistance messages)
|
||||
|
||||
**Posting messages:**
|
||||
- You can post in the faction and public categories only.
|
||||
- Your message will be tagged with the coordinates in the center of the map.
|
||||
- Your zoom level does not matter. Zooming out will not show your messages to more users.
|
||||
|
||||
|
||||
Map Display
|
||||
-----------
|
||||
|
||||
You can customize many aspects of how the map is rendered in the layer chooser.
|
||||
|
||||
**Layer Chooser:**
|
||||
The layer chooser is available from the icon in the top right corner, left of the sidebar. The top entries are background maps and you can only have one of them active at a time. The entries on the bottom can be displayed in any combination you like. *Hint:* (NIGHLTY ONLY) Modifier-click an entry to quickly hide all other layers. The modifier may be either of these: shift, ctrl, alt, meta. Modifier-click the entry again to select all layers.
|
||||
|
||||
**Background / Street Map / Base Layer:**
|
||||
All these refer to the same thing. The base layer is stored across sessions. The default one uses OpenStreetMap data with a style that resembles the default Ingress one. There are other styles available.
|
||||
|
||||
The layers from Google Maps are available as well. Google requires that their maps are only displayed with their tools. Therefore they cannot be as tightly integrated as the OpenStreetMap ones. That’s the reason why they lag behind when zooming or dragging the map.
|
||||
|
||||
**Portals:**
|
||||
You can filter portals by level. Select the ones you want to see in the layer chooser. If lower level portals are striked-through, this means you need to zoom in further to see them. This is a server limitation, not one in IITC. Your settings are discarded after a reload.
|
||||
|
||||
**Resonators:**
|
||||
Resonators are shown at their actual positions if you zoom in close enough. They become lighter the less energy they have left. They are color coded to show their level.
|
||||
|
||||
**Fields / Links:**
|
||||
They are handled the same way portals are, see above.
|
||||
|
||||
**Other:**
|
||||
When you select a portal its outer ring becomes red. There’s also a small yellow circle around it which depicts the hack range. You need to be in hack range to hack the portal or upgrade its resonators or mods.
|
||||
|
||||
If you are zoomed out quite a bit, there’s a larger red circle. This is the link range. Only portals within this link range can be linked while standing at the selected portal. [Click the range in the sidebar to zoom to link range for the selected portal](#random-details).
|
||||
|
||||
**Note** that plugins may also add themselves to the layer chooser.
|
||||
|
||||
|
||||
Map Status / Updates
|
||||
--------------------
|
||||
|
||||
It shows if there are operations currently pending. This includes chat updates as well as map data requests. Updates happen every 45s to 90s, depending on how far zoomed in you are. Zoom in closer for faster updates.
|
||||
|
||||
It also shows which portals are being loaded/shown. Zoom in to see lower level portals. This is a limit of the server and not IITC. Portals levels that cannot be shown are also striked through in the layer chooser.
|
||||
|
||||
**Failures:** If a data request failed, it is retried once. Only if the retry fails as well, a “failure” message is shown in the map status. You can either wait for the next automatic update or move the map a little. Also try to zoom in to request less data, which makes it less likely that the servers fail. The failure counter is reset on the next auto update or if you move the map.
|
||||
|
||||
**Render Limit:** The script tries to stay responsive. If too much data needs to be rendered, this cannot be guaranteed. Instead it will simply stop drawing portals/links/fields and show “render limit” in the map status. Zoom in to solve this.
|
||||
|
||||
|
||||
|
||||
Sidebar
|
||||
-------
|
||||
|
||||
The sidebar is mainly used to show game stats and portal details. However, it also allows you to perform certain actions.
|
||||
|
||||
### General usage:
|
||||
- single click a portal to show details about it in the sidebar.
|
||||
- the portal information is updated automatically, as long as the selected portal is kept in view and you do not zoom out too much.
|
||||
- the sidebar may be collapsed. Click the triangle button that stands out at the left hand side.
|
||||
- the sidebar **can be scrolled** if your screen is too small. Use your scroll wheel.
|
||||
- almost everything has tooltips. See [General usage](#general-usage) above.
|
||||
|
||||
### Details:
|
||||
Starting from the top, the sidebar shows this information:
|
||||
|
||||
#### logged in user, global MU, search
|
||||
- Details about you, the logged in user. This is only updated if you reload the page. This is a limitation of Ingress, not IITC.
|
||||
- it shows your current level followed by your nickname
|
||||
- hovering over your nickname allows you to sign out (NIGHTLY ONLY)
|
||||
- to the right, it shows to percentages. The upper one, e.g. “XM: 37%” tells you how much your XM bar is filled. The lower one, e.g. “level: 37%“ tells you that you have gathered 37% of the AP required for the next level. It shows “max level” if you have reached max level.
|
||||
- the tooltip mainly shows you absolute numbers instead of percentages. It also shows how many invites you have.
|
||||
- The next bar is a visual representation of global MindUnits (MU) per faction. It is updated every now and then. The tooltip shows the absolute MU count per faction.
|
||||
- Search Location: You can search for continents, countries, cities or street addresses. If there is at least one result your are taken to the most likely immediately. There is no feedback if the entered location was not found. Rule of thumb: if it takes longer than three seconds, try again. [Read about supported formats in the user guide for this service](https://wiki.openstreetmap.org/wiki/Nominatim).
|
||||
|
||||
|
||||
#### Portal details.
|
||||
- Portal name, may be abbreviated by the server if it’s too long.
|
||||
- Portal image. Can be clicked to show the full image. The tooltip shows street address and postal code for the portal. It may also show attribution data for the portal image, if available.
|
||||
- Portal level is located in the upper right corner and may overlay the image.
|
||||
|
||||
- Portal mods are shown in right below the portal image. An empty box means that this slot is free and no mod is installed. Otherwise the name of the installed mod is displayed. The color depends on the rare-ness of the mod. Each slot has its own tooltip that shows mod specific details and who installed it.
|
||||
|
||||
##### “random details”
|
||||
“Random Details” are displayed in four columns. The outer ones show the data while the inner ones are the titles.
|
||||
|
||||
- owner: who deployed the first resonator after it has been neutral/unclaimed.
|
||||
- since: when was the first resonator deployed after it has been neutral/unclaimed. The reasonators decay every 24hrs from capture. Move the cursor over it to show the full date time.
|
||||
- range: shows how far links made from this portal can be. Click on the value to zoom out to link range. The red circle shows how far links may reach.
|
||||
- energy: shows current and maximum energy if fully charged. The tooltip contains the exact numbers.
|
||||
- links: shows incoming and outgoing links. The tooltip explains the icons.
|
||||
- reso dist: shows the average distance the resonators have to the portal.
|
||||
- fields: how many fields are connected to this portal
|
||||
- AP Gain: estimate of how many AP you gain if you take down this portal and deploy resonators of your own faction. Tooltip breaks this number down into parts.
|
||||
|
||||
##### Resonators
|
||||
|
||||
The nickname to the left and right show who deployed this resonator. The bars in the middle indicate the charge of each resonator. The color depends on the level, which is also shown in the bar. The tooltip repeats some of that data along with other details. The top left resonator is the north one, top right is north east and so on. They are roughly ordered like they appear on a normal map:
|
||||
```
|
||||
N NE
|
||||
NW E
|
||||
W SE
|
||||
SW S
|
||||
```
|
||||
|
||||
#### portal related links
|
||||
|
||||
- Portal link: use it show others a portal. IITC users will automatically zoomed to the location and shown portal details as soon as they’re available. Vanilla map users will only be zoomed to location.
|
||||
- Report issue: redirects you to Niantic report issue page. Allows you to copy all required information before going there.
|
||||
- poslinks: Shows you a QR-Code containing the geolocation of the portal as well as a link for Google Maps and Openstreetmap. If your QR-Code App supports GEO-codes (most do) you can scan it and pass the portal location directly to a routing-app.
|
||||
|
||||
#### Redeeming, General Links and functions
|
||||
- Redeem code: allows you to redeem codes to receive goodies. If you copied them from the Internet, they are probably invalid already.
|
||||
- Toolbox: plugins may add links here. The default ones are:
|
||||
- permalink. use it to show your current map view to others. Does not select a portal. Works with the normal intel map, too.
|
||||
- IITC’s page. Visit our homepage. Be in awe. Drool.
|
||||
|
||||
|
||||
Reporting Bugs / I need more help
|
||||
---------------------------------
|
||||
|
||||
[Please read the “how do I report bugs” here](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md#how-do-i-report-bugs).
|
||||
[All user documentation has been moved to the wiki. Please see there!](https://github.com/breunigs/ingress-intel-total-conversion/wiki/Userguide-\(Main-Vanilla-IITC\))
|
||||
|
49
code/boot.js
@ -5,6 +5,31 @@
|
||||
// created a basic framework. All of these functions should only ever
|
||||
// be run once.
|
||||
|
||||
|
||||
window.setupBackButton = function() {
|
||||
var c = window.isSmartphone()
|
||||
? window.smartphone.mapButton
|
||||
: $('#chatcontrols a.active');
|
||||
|
||||
window.setupBackButton._actions = [c.get(0)];
|
||||
$('#chatcontrols a').click(function() {
|
||||
// ignore shrink button
|
||||
if($(this).hasClass('toggle')) return;
|
||||
window.setupBackButton._actions.push(this);
|
||||
window.setupBackButton._actions = window.setupBackButton._actions.slice(-2);
|
||||
});
|
||||
|
||||
window.goBack = function() {
|
||||
var a = window.setupBackButton._actions[0];
|
||||
if(!a) return;
|
||||
$(a).click();
|
||||
window.setupBackButton._actions = [a];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
window.setupLargeImagePreview = function() {
|
||||
$('#portaldetails').on('click', '.imgpreview', function() {
|
||||
var ex = $('#largepreview');
|
||||
@ -26,8 +51,9 @@ window.setupLargeImagePreview = function() {
|
||||
// adds listeners to the layer chooser such that a long press hides
|
||||
// all custom layers except the long pressed one.
|
||||
window.setupLayerChooserSelectOne = function() {
|
||||
$('.leaflet-control-layers-overlays').on('click', 'label', function(e) {
|
||||
if(!e || !(e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)) return;
|
||||
$('.leaflet-control-layers-overlays').on('click taphold', 'label', function(e) {
|
||||
if(!e) return;
|
||||
if(!(e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.type === 'taphold')) return;
|
||||
|
||||
var isChecked = $(this).find('input').is(':checked');
|
||||
var checkSize = $('.leaflet-control-layers-overlays input:checked').length;
|
||||
@ -96,10 +122,10 @@ window.setupMap = function() {
|
||||
addLayers['Links'] = linksLayer;
|
||||
|
||||
window.layerChooser = new L.Control.Layers({
|
||||
'OSM Cloudmade Midnight': views[0],
|
||||
'OSM Cloudmade Minimal': views[1],
|
||||
'OSM Midnight': views[0],
|
||||
'OSM Minimal': views[1],
|
||||
'OSM Mapnik': views[2],
|
||||
'Google Roads Ingress Style': views[3],
|
||||
'Default Ingress Map': views[3],
|
||||
'Google Roads': views[4],
|
||||
'Google Satellite': views[5],
|
||||
'Google Hybrid': views[6]
|
||||
@ -260,6 +286,10 @@ window.setupDialogs = function() {
|
||||
}
|
||||
}
|
||||
|
||||
window.setupTaphold = function() {
|
||||
@@INCLUDERAW:external/taphold.js@@
|
||||
}
|
||||
|
||||
|
||||
window.setupQRLoadLib = function() {
|
||||
@@INCLUDERAW:external/jquery.qrcode.min.js@@
|
||||
@ -276,12 +306,13 @@ function boot() {
|
||||
window.runOnSmartphonesBeforeBoot();
|
||||
|
||||
// overwrite default Leaflet Marker icon to be a neutral color
|
||||
var base = 'http://breunigs.github.com/ingress-intel-total-conversion/dist/images/';
|
||||
var base = 'https://iitcserv.appspot.com/dist/images';
|
||||
L.Icon.Default.imagePath = base;
|
||||
|
||||
window.iconEnl = L.Icon.Default.extend({options: { iconUrl: base + 'marker-green.png' } });
|
||||
window.iconRes = L.Icon.Default.extend({options: { iconUrl: base + 'marker-blue.png' } });
|
||||
window.iconEnl = L.Icon.Default.extend({options: { iconUrl: base + '/marker-green.png' } });
|
||||
window.iconRes = L.Icon.Default.extend({options: { iconUrl: base + '/marker-blue.png' } });
|
||||
|
||||
window.setupTaphold();
|
||||
window.setupStyles();
|
||||
window.setupDialogs();
|
||||
window.setupMap();
|
||||
@ -295,6 +326,7 @@ function boot() {
|
||||
window.chat.setup();
|
||||
window.setupQRLoadLib();
|
||||
window.setupLayerChooserSelectOne();
|
||||
window.setupBackButton();
|
||||
// read here ONCE, so the URL is only evaluated one time after the
|
||||
// necessary data has been loaded.
|
||||
urlPortal = getURLParam('pguid');
|
||||
@ -333,6 +365,7 @@ try { console.log('Loading included JS now'); } catch(e) {}
|
||||
// contains the default Ingress map style.
|
||||
@@INCLUDERAW:external/leaflet_google.js@@
|
||||
@@INCLUDERAW:external/autolink.js@@
|
||||
@@INCLUDERAW:external/oms.min.js@@
|
||||
|
||||
try { console.log('done loading included JS'); } catch(e) {}
|
||||
|
||||
|
11
code/chat.js
@ -389,6 +389,7 @@ window.chat.needMoreMessages = function() {
|
||||
if(activeTab === 'debug') return;
|
||||
|
||||
var activeChat = $('#chat > :visible');
|
||||
if(activeChat.length === 0) return;
|
||||
|
||||
var hasScrollbar = scrollBottom(activeChat) !== 0 || activeChat.scrollTop() !== 0;
|
||||
var nearTop = activeChat.scrollTop() <= CHAT_REQUEST_SCROLL_TOP;
|
||||
@ -408,6 +409,7 @@ window.chat.chooser = function(event) {
|
||||
var tt = t.text();
|
||||
|
||||
var mark = $('#chatinput mark');
|
||||
var input = $('#chatinput input');
|
||||
|
||||
$('#chatcontrols .active').removeClass('active');
|
||||
t.addClass('active');
|
||||
@ -418,11 +420,13 @@ window.chat.chooser = function(event) {
|
||||
|
||||
switch(tt) {
|
||||
case 'faction':
|
||||
input.css('color', '');
|
||||
mark.css('color', '');
|
||||
mark.text('tell faction:');
|
||||
break;
|
||||
|
||||
case 'public':
|
||||
input.css('cssText', 'color: red !important');
|
||||
mark.css('cssText', 'color: red !important');
|
||||
mark.text('broadcast:');
|
||||
break;
|
||||
@ -430,6 +434,7 @@ window.chat.chooser = function(event) {
|
||||
case 'compact':
|
||||
case 'full':
|
||||
mark.css('cssText', 'color: #bbb !important');
|
||||
input.css('cssText', 'color: #bbb !important');
|
||||
mark.text('tell Jarvis:');
|
||||
break;
|
||||
|
||||
@ -573,13 +578,13 @@ window.chat.postMsg = function() {
|
||||
|
||||
if(c === 'debug') return new Function (msg)();
|
||||
|
||||
var public = c === 'public';
|
||||
var publik = c === 'public';
|
||||
var latlng = map.getCenter();
|
||||
|
||||
var data = {message: msg,
|
||||
latE6: Math.round(latlng.lat*1E6),
|
||||
lngE6: Math.round(latlng.lng*1E6),
|
||||
factionOnly: !public};
|
||||
factionOnly: !publik};
|
||||
|
||||
var errMsg = 'Your message could not be delivered. You can copy&' +
|
||||
'paste it here and try again if you want:\n\n' + msg;
|
||||
@ -587,7 +592,7 @@ window.chat.postMsg = function() {
|
||||
window.postAjax('sendPlext', data,
|
||||
function(response) {
|
||||
if(response.error) alert(errMsg);
|
||||
if(public) chat.requestPublic(false); else chat.requestFaction(false); },
|
||||
if(publik) chat.requestPublic(false); else chat.requestFaction(false); },
|
||||
function() {
|
||||
alert(errMsg);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ window.setupGeosearch = function() {
|
||||
northEast = new L.LatLng(b[1], b[3]),
|
||||
bounds = new L.LatLngBounds(southWest, northEast);
|
||||
window.map.fitBounds(bounds);
|
||||
if(window.isSmartphone()) window.smartphone.mapButton.click();
|
||||
});
|
||||
e.preventDefault();
|
||||
});
|
||||
|
@ -81,7 +81,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
|
||||
var ppp = [];
|
||||
var p2f = {};
|
||||
$.each(m, function(qk, val) {
|
||||
$.each(val.deletedGameEntityGuids, function(ind, guid) {
|
||||
$.each(val.deletedGameEntityGuids || [], function(ind, guid) {
|
||||
if(getTypeByGuid(guid) === TYPE_FIELD && window.fields[guid] !== undefined) {
|
||||
$.each(window.fields[guid].options.vertices, function(ind, vertex) {
|
||||
if(window.portals[vertex.guid] === undefined) return true;
|
||||
@ -92,7 +92,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
|
||||
window.removeByGuid(guid);
|
||||
});
|
||||
|
||||
$.each(val.gameEntities, function(ind, ent) {
|
||||
$.each(val.gameEntities || [], function(ind, ent) {
|
||||
// ent = [GUID, id(?), details]
|
||||
// format for links: { controllingTeam, creator, edge }
|
||||
// format for portals: { controllingTeam, turret }
|
||||
@ -144,25 +144,26 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
|
||||
}
|
||||
|
||||
window.handlePortalsRender = function(portals) {
|
||||
var portalUpdateAvailable = false;
|
||||
var portalInUrlAvailable = false;
|
||||
|
||||
// Preserve and restore "selectedPortal" between portal re-render
|
||||
if(portalUpdateAvailable) var oldSelectedPortal = selectedPortal;
|
||||
// Preserve selectedPortal because it will get lost on re-rendering
|
||||
// the portal
|
||||
var oldSelectedPortal = selectedPortal;
|
||||
|
||||
runHooks('portalDataLoaded', {portals : portals});
|
||||
$.each(portals, function(ind, portal) {
|
||||
if(selectedPortal === portal[0]) portalUpdateAvailable = true;
|
||||
if(urlPortal && portal[0] == urlPortal) portalInUrlAvailable = true;
|
||||
//~ if(selectedPortal === portal[0]) portalUpdateAvailable = true;
|
||||
if(urlPortal && portal[0] === urlPortal) portalInUrlAvailable = true;
|
||||
renderPortal(portal);
|
||||
});
|
||||
|
||||
var selectedPortalLayer = portals[oldSelectedPortal];
|
||||
if(portalUpdateAvailable && selectedPortalLayer) selectedPortal = oldSelectedPortal;
|
||||
|
||||
if(selectedPortalLayer) {
|
||||
// restore selected portal if still available
|
||||
var selectedPortalGroup = portals[oldSelectedPortal];
|
||||
if(selectedPortalGroup) {
|
||||
selectedPortal = oldSelectedPortal;
|
||||
renderPortalDetails(selectedPortal);
|
||||
try {
|
||||
selectedPortalLayer.bringToFront();
|
||||
selectedPortalGroup.bringToFront();
|
||||
} catch(e) { /* portal is now visible, catch Leaflet error */ }
|
||||
}
|
||||
|
||||
@ -170,8 +171,6 @@ window.handlePortalsRender = function(portals) {
|
||||
renderPortalDetails(urlPortal);
|
||||
urlPortal = null; // select it only once
|
||||
}
|
||||
|
||||
if(portalUpdateAvailable) renderPortalDetails(selectedPortal);
|
||||
}
|
||||
|
||||
// removes entities that are still handled by Leaflet, although they
|
||||
|
@ -3,44 +3,69 @@
|
||||
// REDEEMING /////////////////////////////////////////////////////////
|
||||
|
||||
window.handleRedeemResponse = function(data, textStatus, jqXHR) {
|
||||
if (data.error) {
|
||||
if(data.error) {
|
||||
var error = '';
|
||||
if (data.error === 'ALREADY_REDEEMED') {
|
||||
if(data.error === 'ALREADY_REDEEMED') {
|
||||
error = 'The passcode has already been redeemed.';
|
||||
} else if (data.error === 'ALREADY_REDEEMED_BY_PLAYER') {
|
||||
} else if(data.error === 'ALREADY_REDEEMED_BY_PLAYER') {
|
||||
error = 'You have already redeemed this passcode.';
|
||||
} else if (data.error === 'INVALID_PASSCODE') {
|
||||
} else if(data.error === 'INVALID_PASSCODE') {
|
||||
error = 'This passcode is invalid.';
|
||||
} else {
|
||||
error = 'There was a problem redeeming the passcode. Try again?';
|
||||
}
|
||||
alert('<strong>' + data.error + '</strong>\n' + error);
|
||||
} else if (data.result) {
|
||||
var xmp_level = 0, xmp_count = 0;
|
||||
var res_level = 0, res_count = 0;
|
||||
var shield_rarity = '', shield_count = 0;
|
||||
} else if(data.result) {
|
||||
var tblResult = $('<table class="redeem-result" />');
|
||||
tblResult.append($('<tr><th colspan="2">Passcode accepted!</th></tr>'));
|
||||
|
||||
// This assumes that each passcode gives only one type of resonator/XMP/shield.
|
||||
// This may break at some point, depending on changes to passcode functionality.
|
||||
for (var i in data.result.inventoryAward) {
|
||||
if(data.result.apAward)
|
||||
tblResult.append($('<tr><td>+</td><td>' + data.result.apAward + 'AP</td></tr>'));
|
||||
if(data.result.xmAward)
|
||||
tblResult.append($('<tr><td>+</td><td>' + data.result.xmAward + 'XM</td></tr>'));
|
||||
|
||||
var resonators = {};
|
||||
var bursts = {};
|
||||
var shields = {};
|
||||
|
||||
for(var i in data.result.inventoryAward) {
|
||||
var acquired = data.result.inventoryAward[i][2];
|
||||
if (acquired.modResource) {
|
||||
if (acquired.modResource.resourceType === 'RES_SHIELD') {
|
||||
shield_rarity = acquired.modResource.rarity.split('_').map(function (i) {return i[0]}).join('');
|
||||
shield_count++;
|
||||
if(acquired.modResource) {
|
||||
if(acquired.modResource.resourceType === 'RES_SHIELD') {
|
||||
var rarity = acquired.modResource.rarity.split('_').map(function (i) {return i[0]}).join('');
|
||||
if(!shields[rarity]) shields[rarity] = 0;
|
||||
shields[rarity] += 1;
|
||||
}
|
||||
} else if (acquired.resourceWithLevels) {
|
||||
if (acquired.resourceWithLevels.resourceType === 'EMP_BURSTER') {
|
||||
xmp_level = acquired.resourceWithLevels.level;
|
||||
xmp_count++;
|
||||
} else if (acquired.resourceWithLevels.resourceType === 'EMITTER_A') {
|
||||
res_level = acquired.resourceWithLevels.level;
|
||||
res_count++;
|
||||
} else if(acquired.resourceWithLevels) {
|
||||
if(acquired.resourceWithLevels.resourceType === 'EMITTER_A') {
|
||||
var level = acquired.resourceWithLevels.level
|
||||
if(!resonators[level]) resonators[level] = 0;
|
||||
resonators[level] += 1;
|
||||
} else if(acquired.resourceWithLevels.resourceType === 'EMP_BURSTER') {
|
||||
var level = acquired.resourceWithLevels.level
|
||||
if(!bursts[level]) bursts[level] = 0;
|
||||
bursts[level] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
alert('<strong>Passcode accepted!</strong>\n' + [data.result.apAward + 'AP', data.result.xmAward + 'XM', xmp_count + 'xL' + xmp_level + ' XMP', res_count + 'xL' + res_level + ' RES', shield_count + 'x' + shield_rarity + ' SH'].join('/'));
|
||||
$.each(resonators, function(lvl, count) {
|
||||
var text = 'Resonator';
|
||||
if(count >= 2) text += ' ('+count+')';
|
||||
tblResult.append($('<tr ><td style="color: ' +window.COLORS_LVL[lvl]+ ';">L' +lvl+ '</td><td>' + text + '</td></tr>'));
|
||||
});
|
||||
$.each(bursts, function(lvl, count) {
|
||||
var text = 'Xmp Burster';
|
||||
if(count >= 2) text += ' ('+count+')';
|
||||
tblResult.append($('<tr ><td style="color: ' +window.COLORS_LVL[lvl]+ ';">L' +lvl+ '</td><td>' + text + '</td></tr>'));
|
||||
});
|
||||
$.each(shields, function(lvl, count) {
|
||||
var text = 'Portal Shield';
|
||||
if(count >= 2) text += ' ('+count+')';
|
||||
tblResult.append($('<tr><td>'+lvl+'</td><td>'+text+'</td></tr>'));
|
||||
});
|
||||
|
||||
alert(tblResult, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,8 +76,8 @@ window.setupRedeem = function() {
|
||||
window.postAjax('redeemReward', data, window.handleRedeemResponse,
|
||||
function(response) {
|
||||
var extra = '';
|
||||
if (response && response.status) {
|
||||
if (response.status === 429) {
|
||||
if(response && response.status) {
|
||||
if(response.status === 429) {
|
||||
extra = 'You have been rate-limited by the server. Wait a bit and try again.';
|
||||
} else {
|
||||
extra = 'The server indicated an error.';
|
||||
|
@ -49,13 +49,6 @@ window.runOnSmartphonesBeforeBoot = function() {
|
||||
|
||||
$('#chatcontrols').append(smartphone.mapButton).append(smartphone.sideButton);
|
||||
|
||||
// add event to portals that allows long press to switch to sidebar
|
||||
window.addHook('portalAdded', function(data) {
|
||||
data.portal.on('dblclick', function() {
|
||||
window.lastClickedPortal = this.options.guid;
|
||||
});
|
||||
});
|
||||
|
||||
window.addHook('portalDetailsUpdated', function(data) {
|
||||
var x = $('.imgpreview img').removeClass('hide');
|
||||
|
||||
@ -83,4 +76,23 @@ window.runOnSmartphonesAfterBoot = function() {
|
||||
$('#portaldetails').off('click', '**');
|
||||
|
||||
$('.leaflet-right').addClass('leaflet-left').removeClass('leaflet-right');
|
||||
|
||||
// make buttons in action bar flexible
|
||||
var l = $('#chatcontrols a:visible');
|
||||
l.css('width', 100/l.length + '%');
|
||||
|
||||
// add event to portals that allows long press to switch to sidebar
|
||||
window.addHook('portalAdded', function(data) {
|
||||
data.portal.on('add', function() {
|
||||
if(!this._container || this.options.addedTapHoldHandler) return;
|
||||
this.options.addedTapHoldHandler = true;
|
||||
var guid = this.options.guid;
|
||||
|
||||
// this is a hack, accessing Leaflet’s private _container is evil
|
||||
$(this._container).on('taphold', function() {
|
||||
window.renderPortalDetails(guid);
|
||||
window.smartphone.sideButton.click();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ window.setPermaLink = function(elm) {
|
||||
var lat = Math.round(c.lat*1E6);
|
||||
var lng = Math.round(c.lng*1E6);
|
||||
var qry = 'latE6='+lat+'&lngE6='+lng+'&z=' + (map.getZoom()-1);
|
||||
$(elm).attr('href', 'http://www.ingress.com/intel?' + qry);
|
||||
$(elm).attr('href', 'https://www.ingress.com/intel?' + qry);
|
||||
}
|
||||
|
||||
window.uniqueArray = function(arr) {
|
||||
|
BIN
dist/images/marker-blue_2x.png
vendored
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
dist/images/marker-green_2x.png
vendored
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
dist/images/marker-icon_2x.png
vendored
Normal file
After Width: | Height: | Size: 2.7 KiB |
4
dist/total-conversion-build.user.js
vendored
@ -1243,7 +1243,7 @@ window.setPermaLink = function(elm) {
|
||||
var lat = Math.round(c.lat*1E6);
|
||||
var lng = Math.round(c.lng*1E6);
|
||||
var qry = 'latE6='+lat+'&lngE6='+lng+'&z=' + (map.getZoom()-1);
|
||||
$(elm).attr('href', 'http://www.ingress.com/intel?' + qry);
|
||||
$(elm).attr('href', 'https://www.ingress.com/intel?' + qry);
|
||||
}
|
||||
|
||||
window.uniqueArray = function(arr) {
|
||||
@ -2833,7 +2833,7 @@ window.renderPortalDetails = function(guid) {
|
||||
|
||||
var lat = d.locationE6.latE6;
|
||||
var lng = d.locationE6.lngE6;
|
||||
var perma = 'http://ingress.com/intel?latE6='+lat+'&lngE6='+lng+'&z=17&pguid='+guid;
|
||||
var perma = 'https://ingress.com/intel?latE6='+lat+'&lngE6='+lng+'&z=17&pguid='+guid;
|
||||
var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."';
|
||||
var poslinks = 'window.showPortalPosLinks('+lat/1E6+','+lng/1E6+')';
|
||||
var postcard = 'Send in a postcard. Will put it online after receiving. Address:\\n\\nStefan Breunig\\nINF 305 – R045\\n69120 Heidelberg\\nGermany';
|
||||
|
2
external/leaflet.js
vendored
19
external/oms.min.js
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
(function(){/*
|
||||
OverlappingMarkerSpiderfier
|
||||
https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet
|
||||
Copyright (c) 2011 - 2012 George MacKerron
|
||||
Released under the MIT licence: http://opensource.org/licenses/mit-license
|
||||
Note: The Leaflet maps API must be included *before* this code
|
||||
*/
|
||||
(function(){var n={}.hasOwnProperty,o=[].slice;null!=this.L&&(this.OverlappingMarkerSpiderfier=function(){function l(c,b){var a,e,g,f,d=this;this.map=c;null==b&&(b={});for(a in b)n.call(b,a)&&(e=b[a],this[a]=e);this.initMarkerArrays();this.listeners={};f=["click","zoomend"];e=0;for(g=f.length;e<g;e++)a=f[e],this.map.addEventListener(a,function(){return d.unspiderfy()})}var d,i;d=l.prototype;d.VERSION="0.2.5";i=2*Math.PI;d.keepSpiderfied=!1;d.nearbyDistance=20;d.circleSpiralSwitchover=9;d.circleFootSeparation=
|
||||
25;d.circleStartAngle=i/12;d.spiralFootSeparation=28;d.spiralLengthStart=11;d.spiralLengthFactor=5;d.legWeight=1.5;d.legColors={usual:"#222",highlighted:"#f00"};d.initMarkerArrays=function(){this.markers=[];return this.markerListeners=[]};d.addMarker=function(c){var b,a=this;if(null!=c._oms)return this;c._oms=!0;b=function(){return a.spiderListener(c)};c.addEventListener("click",b);this.markerListeners.push(b);this.markers.push(c);return this};d.getMarkers=function(){return this.markers.slice(0)};
|
||||
d.removeMarker=function(c){var b,a;null!=c._omsData&&this.unspiderfy();b=this.arrIndexOf(this.markers,c);if(0>b)return this;a=this.markerListeners.splice(b,1)[0];c.removeEventListener("click",a);delete c._oms;this.markers.splice(b,1);return this};d.clearMarkers=function(){var c,b,a,e,g;this.unspiderfy();g=this.markers;c=a=0;for(e=g.length;a<e;c=++a)b=g[c],c=this.markerListeners[c],b.removeEventListener("click",c),delete b._oms;this.initMarkerArrays();return this};d.addListener=function(c,b){var a,
|
||||
e;(null!=(e=(a=this.listeners)[c])?e:a[c]=[]).push(b);return this};d.removeListener=function(c,b){var a;a=this.arrIndexOf(this.listeners[c],b);0>a||this.listeners[c].splice(a,1);return this};d.clearListeners=function(c){this.listeners[c]=[];return this};d.trigger=function(){var c,b,a,e,g,f;b=arguments[0];c=2<=arguments.length?o.call(arguments,1):[];b=null!=(a=this.listeners[b])?a:[];f=[];e=0;for(g=b.length;e<g;e++)a=b[e],f.push(a.apply(null,c));return f};d.generatePtsCircle=function(c,b){var a,e,
|
||||
g,f,d;g=this.circleFootSeparation*(2+c)/i;e=i/c;d=[];for(a=f=0;0<=c?f<c:f>c;a=0<=c?++f:--f)a=this.circleStartAngle+a*e,d.push(new L.Point(b.x+g*Math.cos(a),b.y+g*Math.sin(a)));return d};d.generatePtsSpiral=function(c,b){var a,e,g,f,d;g=this.spiralLengthStart;a=0;d=[];for(e=f=0;0<=c?f<c:f>c;e=0<=c?++f:--f)a+=this.spiralFootSeparation/g+5.0E-4*e,e=new L.Point(b.x+g*Math.cos(a),b.y+g*Math.sin(a)),g+=i*this.spiralLengthFactor/a,d.push(e);return d};d.spiderListener=function(c){var b,a,e,g,f,d,h,i,j;b=
|
||||
null!=c._omsData;(!b||!this.keepSpiderfied)&&this.unspiderfy();if(b)return this.trigger("click",c);g=[];f=[];d=this.nearbyDistance*this.nearbyDistance;e=this.map.latLngToLayerPoint(c.getLatLng());j=this.markers;h=0;for(i=j.length;h<i;h++)b=j[h],a=this.map.latLngToLayerPoint(b.getLatLng()),this.ptDistanceSq(a,e)<d?g.push({marker:b,markerPt:a}):f.push(b);return 1===g.length?this.trigger("click",c):this.spiderfy(g,f)};d.makeHighlightListeners=function(c){var b=this;return{highlight:function(){return c._omsData.leg.setStyle({color:b.legColors.highlighted})},
|
||||
unhighlight:function(){return c._omsData.leg.setStyle({color:b.legColors.usual})}}};d.spiderfy=function(c,b){var a,e,g,d,m,h,i,j,l,k;this.spiderfying=!0;k=c.length;a=this.ptAverage(function(){var a,b,e;e=[];a=0;for(b=c.length;a<b;a++)i=c[a],e.push(i.markerPt);return e}());d=k>=this.circleSpiralSwitchover?this.generatePtsSpiral(k,a).reverse():this.generatePtsCircle(k,a);a=function(){var a,b,i,k=this;i=[];a=0;for(b=d.length;a<b;a++)g=d[a],e=this.map.layerPointToLatLng(g),l=this.minExtract(c,function(a){return k.ptDistanceSq(a.markerPt,
|
||||
g)}),h=l.marker,m=new L.Polyline([h.getLatLng(),e],{color:this.legColors.usual,weight:this.legWeight,clickable:!1}),this.map.addLayer(m),h._omsData={usualPosition:h.getLatLng(),leg:m},this.legColors.highlighted!==this.legColors.usual&&(j=this.makeHighlightListeners(h),h._omsData.highlightListeners=j,h.addEventListener("mouseover",j.highlight),h.addEventListener("mouseout",j.unhighlight)),h.setLatLng(e),h.setZIndexOffset(1E6),i.push(h);return i}.call(this);delete this.spiderfying;this.spiderfied=!0;
|
||||
return this.trigger("spiderfy",a,b)};d.unspiderfy=function(c){var b,a,e,d,f,i,h;null==c&&(c=null);if(null==this.spiderfied)return this;this.unspiderfying=!0;d=[];e=[];h=this.markers;f=0;for(i=h.length;f<i;f++)b=h[f],null!=b._omsData?(this.map.removeLayer(b._omsData.leg),b!==c&&b.setLatLng(b._omsData.usualPosition),b.setZIndexOffset(0),a=b._omsData.highlightListeners,null!=a&&(b.removeEventListener("mouseover",a.highlight),b.removeEventListener("mouseout",a.unhighlight)),delete b._omsData,d.push(b)):
|
||||
e.push(b);delete this.unspiderfying;delete this.spiderfied;this.trigger("unspiderfy",d,e);return this};d.ptDistanceSq=function(c,b){var a,e;a=c.x-b.x;e=c.y-b.y;return a*a+e*e};d.ptAverage=function(c){var b,a,e,d,f;d=a=e=0;for(f=c.length;d<f;d++)b=c[d],a+=b.x,e+=b.y;c=c.length;return new L.Point(a/c,e/c)};d.minExtract=function(c,b){var a,d,g,f,i,h;g=i=0;for(h=c.length;i<h;g=++i)if(f=c[g],f=b(f),!("undefined"!==typeof a&&null!==a)||f<d)d=f,a=g;return c.splice(a,1)[0]};d.arrIndexOf=function(c,b){var a,
|
||||
d,g,f;if(null!=c.indexOf)return c.indexOf(b);a=g=0;for(f=c.length;g<f;a=++g)if(d=c[a],d===b)return a;return-1};return l}())}).call(this);}).call(this);
|
||||
/* Sun 6 May 2012 17:49:10 BST */
|
106
external/taphold.js
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
// @author Rich Adams <rich@richadams.me>
|
||||
|
||||
// Implements a tap and hold functionality. If you click/tap and release, it will trigger a normal
|
||||
// click event. But if you click/tap and hold for 1s, it will trigger a taphold event instead.
|
||||
|
||||
;(function($)
|
||||
{
|
||||
// When start of a taphold event is triggered.
|
||||
function startHandler(event)
|
||||
{
|
||||
var $elem = jQuery(this);
|
||||
|
||||
// If object also has click handler, store it and unbind. Taphold will trigger the
|
||||
// click itself, rather than normal propagation.
|
||||
if (typeof $elem.data("events") != "undefined"
|
||||
&& typeof $elem.data("events").click != "undefined")
|
||||
{
|
||||
// Find the one without a namespace defined.
|
||||
for (var c in $elem.data("events").click)
|
||||
{
|
||||
if ($elem.data("events").click[c].namespace == "")
|
||||
{
|
||||
var handler = $elem.data("events").click[c].handler
|
||||
$elem.data("taphold_click_handler", handler);
|
||||
$elem.unbind("click", handler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Otherwise, if a custom click handler was explicitly defined, then store it instead.
|
||||
else if (typeof event.data != "undefined"
|
||||
&& event.data != null
|
||||
&& typeof event.data.clickHandler == "function")
|
||||
{
|
||||
$elem.data("taphold_click_handler", event.data.clickHandler);
|
||||
}
|
||||
|
||||
// Reset the flags
|
||||
$elem.data("taphold_triggered", false); // If a hold was triggered
|
||||
$elem.data("taphold_clicked", false); // If a click was triggered
|
||||
$elem.data("taphold_cancelled", false); // If event has been cancelled.
|
||||
|
||||
// Set the timer for the hold event.
|
||||
$elem.data("taphold_timer",
|
||||
setTimeout(function()
|
||||
{
|
||||
// If event hasn't been cancelled/clicked already, then go ahead and trigger the hold.
|
||||
if (!$elem.data("taphold_cancelled")
|
||||
&& !$elem.data("taphold_clicked"))
|
||||
{
|
||||
// Trigger the hold event, and set the flag to say it's been triggered.
|
||||
$elem.trigger(jQuery.extend(event, jQuery.Event("taphold")));
|
||||
$elem.data("taphold_triggered", true);
|
||||
}
|
||||
}, 1000));
|
||||
}
|
||||
|
||||
// When user ends a tap or click, decide what we should do.
|
||||
function stopHandler(event)
|
||||
{
|
||||
var $elem = jQuery(this);
|
||||
|
||||
// If taphold has been cancelled, then we're done.
|
||||
if ($elem.data("taphold_cancelled")) { return; }
|
||||
|
||||
// Clear the hold timer. If it hasn't already triggered, then it's too late anyway.
|
||||
clearTimeout($elem.data("taphold_timer"));
|
||||
|
||||
// If hold wasn't triggered and not already clicked, then was a click event.
|
||||
if (!$elem.data("taphold_triggered")
|
||||
&& !$elem.data("taphold_clicked"))
|
||||
{
|
||||
// If click handler, trigger it.
|
||||
if (typeof $elem.data("taphold_click_handler") == "function")
|
||||
{
|
||||
$elem.data("taphold_click_handler")(jQuery.extend(event, jQuery.Event("click")));
|
||||
}
|
||||
|
||||
// Set flag to say we've triggered the click event.
|
||||
$elem.data("taphold_clicked", true);
|
||||
}
|
||||
}
|
||||
|
||||
// If a user prematurely leaves the boundary of the object we're working on.
|
||||
function leaveHandler(event)
|
||||
{
|
||||
// Cancel the event.
|
||||
$(this).data("taphold_cancelled", true);
|
||||
}
|
||||
|
||||
var taphold = $.event.special.taphold =
|
||||
{
|
||||
setup: function(data)
|
||||
{
|
||||
$(this).bind("touchstart mousedown", data, startHandler)
|
||||
.bind("touchend mouseup", stopHandler)
|
||||
.bind("touchmove mouseleave", leaveHandler);
|
||||
},
|
||||
teardown: function(namespaces)
|
||||
{
|
||||
$(this).unbind("touchstart mousedown", startHandler)
|
||||
.unbind("touchend mouseup", stopHandler)
|
||||
.unbind("touchmove mouseleave", leaveHandler);
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
BIN
images/marker-blue_2x.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
images/marker-green_2x.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
images/marker-icon_2x.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
4
main.js
@ -42,8 +42,8 @@ if(!d) {
|
||||
// page doesn’t have a script tag with player information.
|
||||
if(document.getElementById('header_email')) {
|
||||
// however, we are logged in.
|
||||
setTimeout('location.reload();', 10*1000);
|
||||
throw('Page doesn’t have player data, but you are logged in. Reloading in 10s.');
|
||||
setTimeout('location.reload();', 3*1000);
|
||||
throw('Page doesn’t have player data, but you are logged in. Reloading in 3s.');
|
||||
}
|
||||
// FIXME: handle nia takedown in progress
|
||||
throw('Couldn’t retrieve player data. Are you logged in?');
|
||||
|
9
mobile/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
assets/
|
||||
bin/
|
||||
gen/
|
||||
libs/
|
||||
proguard-project.txt
|
||||
local.properties
|
37
mobile/AndroidManifest.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.cradle.iitc_mobile"
|
||||
android:versionCode="1"
|
||||
android:versionName="0.1.5" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="8"
|
||||
android:targetSdkVersion="10" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ingress_iitc"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name="com.cradle.iitc_mobile.IITC_Mobile"
|
||||
android:theme="@android:style/Theme.NoTitleBar"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="orientation|keyboard|keyboardHidden|screenSize" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:host="www.ingress.com" android:scheme="https" android:pathPrefix="/intel"></data>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
24
mobile/HACKING.md
Normal file
@ -0,0 +1,24 @@
|
||||
How does this basically work?
|
||||
-----------------------------
|
||||
|
||||
At the moment, the Android App is nothing more then a WebView which renders the normal web page. The IITC script is injected on page load and after this, it works the same way as on desktop browser. More functionality will be added soon...
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
If you want to debug the APK, I suggest [reading up on Google’s documentation](https://developer.android.com/index.html).
|
||||
|
||||
Debugging IITC(M) **after** it has booted is relatively easy: you can switch to the “debug” tab, which is a low end developer console. It renders all calls to `console.*`, so you can use it just like you expect. It may be easier to develop in a desktop browser. Set it up like explained [in the normal hacking guide](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md), but fake your user agent or modify the detection in `code/smartphone.js` and `main.js`. The device ID is printed to the debug console on IITC boot.
|
||||
|
||||
Debugging IITC(M) **before** it has booted requires the Android Developer Tools. Connecting your device and running `adb logcat` should print the debug log to your computer until the low-end dev console mentioned above is available.
|
||||
|
||||
|
||||
Building the APK
|
||||
----------------
|
||||
|
||||
- **Eclipse:** Just import this project and klick the build button.
|
||||
- **ant:**
|
||||
Set the ANDROID_HOME environment variable:
|
||||
```export ANDROID_HOME=/path/to/android_sdk```
|
||||
and build the project with ant:
|
||||
`ant debug`
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>AppTemplate</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.jakbox.ingressTC"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="8"
|
||||
android:targetSdkVersion="14" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_GPS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:hardwareAccelerated="false"
|
||||
android:largeHeap="false"
|
||||
android:debuggable="true">
|
||||
<activity
|
||||
android:label="@string/app_name"
|
||||
android:name=".MainActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden">
|
||||
<intent-filter >
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -1,6 +0,0 @@
|
||||
/** Automatically generated file. DO NOT MODIFY */
|
||||
package com.jakbox.ingressTC;
|
||||
|
||||
public final class BuildConfig {
|
||||
public final static boolean DEBUG = true;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/* AUTO-GENERATED FILE. DO NOT MODIFY.
|
||||
*
|
||||
* This class was automatically generated by the
|
||||
* aapt tool from the resource data it found. It
|
||||
* should not be modified by hand.
|
||||
*/
|
||||
|
||||
package com.jakbox.ingressTC;
|
||||
|
||||
public final class R {
|
||||
public static final class attr {
|
||||
}
|
||||
public static final class drawable {
|
||||
public static final int ic_launcher=0x7f020000;
|
||||
}
|
||||
public static final class layout {
|
||||
public static final int main=0x7f030000;
|
||||
}
|
||||
public static final class raw {
|
||||
public static final int loader=0x7f040000;
|
||||
}
|
||||
public static final class string {
|
||||
public static final int app_name=0x7f050000;
|
||||
public static final int first_page=0x7f050001;
|
||||
public static final int jakboxBootLoader=0x7f050002;
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 21 KiB |
@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical" >
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/first_page" />
|
||||
</LinearLayout>
|
@ -1,13 +0,0 @@
|
||||
function rebuildUI() {
|
||||
if(window.UIDone == true) { return; }
|
||||
if(!document.getElementById("map_canvas")) {
|
||||
setTimeout(rebuildUI, 50);
|
||||
return;
|
||||
} else {
|
||||
window.UIDone = true;
|
||||
}
|
||||
window.console.log(window.deviceID);
|
||||
window.loadJS("http://mathphys.fsk.uni-heidelberg.de:8000/test.js")
|
||||
//window.Android.TCReady();
|
||||
}
|
||||
rebuildUI();
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Ingress Intel Total Conversion</string>
|
||||
<string name="first_page">Connecting to Ingress Intel Map ... </string>
|
||||
<string name="jakboxBootLoader">
|
||||
bootLoader = function() {
|
||||
if(document.getElementById(\"map_canvas\")) {
|
||||
window.stop();
|
||||
document.body.innerHTML = "";
|
||||
} else {
|
||||
setTimeout(bootLoader, 50);
|
||||
}
|
||||
};
|
||||
setTimeout(bootLoader, 5);
|
||||
</string>
|
||||
|
||||
</resources>
|
@ -1,149 +0,0 @@
|
||||
/********************************************************************************
|
||||
Ingress Intel Total Converion - Mobile & Tablet
|
||||
Android WebView wrapper/loader for iitc (ingress intel total conversion)
|
||||
iitc source @ https://github.com/breunigs/ingress-intel-total-conversion
|
||||
|
||||
Original Author: Jason Grima - jason@jakbox.net
|
||||
*********************************************************************************/
|
||||
|
||||
|
||||
package com.jakbox.ingressTC;
|
||||
|
||||
import android.app.*;
|
||||
import android.os.*;
|
||||
import android.content.Context;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
import android.webkit.*;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.util.Log;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.BufferedReader;
|
||||
import java.lang.StringBuffer;
|
||||
|
||||
public class MainActivity extends Activity
|
||||
{
|
||||
WebView web; // webview to hold the ingress site (and login etc)
|
||||
WebView splash; // splash screen, just a bit of pretty
|
||||
MyChrome chrome; // for logging, progress, etc
|
||||
MyClient client; // for controlling the webview's
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE); // hide the app title bar, Xeen requested
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// little animated title/splash page for IngressIntelTC
|
||||
// separate webview so we can be loading stuff in the background
|
||||
JSInterface js = new JSInterface(this, this); //js.setActivity(this);
|
||||
this.splash = new WebView(this);
|
||||
splash.getSettings().setJavaScriptEnabled(true); // because we use JS to trigger the CSS animation
|
||||
splash.getSettings().setAllowFileAccess(true); // because the splash page is store in the apk
|
||||
splash.getSettings().setAllowFileAccessFromFileURLs(true); // in case we add more scripts/images to the splash page
|
||||
splash.loadUrl("file:///android_asset/js/ingressSplash.html"); // there is is!
|
||||
splash.addJavascriptInterface(js, "android");
|
||||
setContentView(splash);
|
||||
// righto, load the the website (ingress.com/intel) with a bunch of permissions that may/or not be needed
|
||||
this.web = new WebView(this);
|
||||
this.client = new MyClient();
|
||||
web.setWebViewClient(this.client);
|
||||
web.getSettings().setJavaScriptEnabled(true);
|
||||
web.getSettings().setGeolocationEnabled(true);
|
||||
web.getSettings().setAllowFileAccess(true);
|
||||
web.getSettings().setAllowFileAccessFromFileURLs(true);
|
||||
web.getSettings().setDatabaseEnabled(true);
|
||||
web.getSettings().setDomStorageEnabled(true);
|
||||
web.getSettings().setGeolocationEnabled(true);
|
||||
|
||||
this.chrome = new MyChrome(); // the chrome let's us get console and progress feedback from the page
|
||||
web.setWebChromeClient(this.chrome);
|
||||
web.addJavascriptInterface(js, "android"); // ready to go
|
||||
|
||||
}
|
||||
|
||||
public void onRestoreInstanceState(Bundle state) {
|
||||
this.splash.restoreState(state);
|
||||
this.web.restoreState(state);
|
||||
}
|
||||
public void onSaveInstanceState(Bundle state) {
|
||||
this.splash.saveState(state);
|
||||
this.web.saveState(state);
|
||||
}
|
||||
|
||||
public void showWeb() { setContentView(web); splash.destroy(); Log.d("com.jakbox.ingressTC", "Flipping to web/ingress view"); }
|
||||
public void showSplash() { setContentView(splash); web.destroy(); Log.d("com.jakbox.ingressTC", "Flipping to splash/loading"); }
|
||||
|
||||
final class JSInterface {
|
||||
Context context; MainActivity act;
|
||||
public JSInterface (Context c, MainActivity a) { this.context = c; this.act = a; }
|
||||
public void setActivity(MainActivity a) { this.act = a; }
|
||||
// the @JavascriptInterface is needed for 4.2 devices to access this
|
||||
@JavascriptInterface
|
||||
public void pageReady(int ready) {
|
||||
if(ready != 0) {
|
||||
// the loader reports we're good to go, switch to ingress webview
|
||||
this.act.runOnUiThread(new Runnable() {
|
||||
public void run() { showWeb(); }
|
||||
});
|
||||
} else {
|
||||
// the loader reports we're not ready, switch to splash page
|
||||
this.act.runOnUiThread(new Runnable() {
|
||||
public void run() { showSplash(); }
|
||||
});
|
||||
}
|
||||
}
|
||||
@JavascriptInterface
|
||||
public void loadBehind(final String url) {
|
||||
this.act.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
Log.d("com.jakbox.ingressTC", "Loading (Ingress?) website in back webview");
|
||||
web.loadUrl(url); /* push the url to the webview */ }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class MyClient extends WebViewClient {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView web, String Url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView web, String Url) {
|
||||
// here we conditionally load some external javascript
|
||||
Log.d("com.jakbox.ingressTC", "Page loading, injecting IITC JS");
|
||||
if(web.getUrl().contains("ingress.com/intel")) {
|
||||
// if NOT ingress, we may have been redirected to the google auth/login page
|
||||
web.loadUrl("javascript: window.stop(); ");
|
||||
// first stop the page from loading too much
|
||||
web.loadUrl("javascript: window.deviceID='"+Secure.getString(getContentResolver(), Secure.ANDROID_ID)+"'; ");
|
||||
// create a JS loader on the page
|
||||
web.loadUrl("javascript: if(!window.loadJS) { window.loadJS = function(scr) { var s = document.createElement('script'); s.src = scr+(scr.indexOf('file:///')==-1?'?ts="+System.currentTimeMillis()+"':''); s.type = 'text/javascript'; s.async = true; var st = document.getElementsByTagName('script')[0]; st.parentNode.insertBefore(s, st); } };");
|
||||
// actually hijack the page... if it's the right page... let the loader deal with that
|
||||
// should pull this loader into a local resource, maybe...
|
||||
// running it from the web for now ...
|
||||
web.loadUrl("javascript: if(!window.hijacked) { window.loadJS('http://mathphys.fsk.uni-heidelberg.de:8000/bootstrap.js'); window.hijacked = true;}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyChrome extends WebChromeClient {
|
||||
@Override
|
||||
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
|
||||
// Always grant permission since the app itself requires location
|
||||
// permission and the user has therefore already granted it
|
||||
callback.invoke(origin, true, false);
|
||||
}
|
||||
|
||||
public boolean onConsoleMessage(ConsoleMessage cm) {
|
||||
// log window.console stuff into the syslog for ADB output
|
||||
Log.d("com.jakbox.ingressTC", cm.message() + " -- "
|
||||
+ (cm.sourceId()==null?"main document":cm.sourceId())
|
||||
+ ":Line " + cm.lineNumber() );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,75 +1,6 @@
|
||||
IITC Mobile (IITCM)
|
||||
===================
|
||||
ingress intel total conversion (IITC)
|
||||
=====================================
|
||||
|
||||
```
|
||||
# # ####### ####### ###### ####### # ###### # #
|
||||
## # # # # # # # # # # # # #
|
||||
# # # # # # # # # # # # # # #
|
||||
# # # # # # ###### ##### # # # # #
|
||||
# # # # # # # # # ####### # # #
|
||||
# ## # # # # # # # # # # #
|
||||
# # ####### # # # ####### # # ###### #
|
||||
```
|
||||
# [User documentation moved to the wiki. Please see there!](https://github.com/breunigs/ingress-intel-total-conversion/wiki/IITC-Mobile)
|
||||
|
||||
- This is **alpha quality** software
|
||||
- There are more bugs than in all Indiana Jones titles combined
|
||||
- It will kill your data plan. Caching has been explicitly disabled for testing, so every restart nets you ~500 KiB of code. Since it uses raster maps instead of vector ones, the transfer volume is larger than for Google Maps, too.
|
||||
|
||||
|
||||
### read this guide thoroughly.
|
||||
|
||||
How to report bugs
|
||||
------------------
|
||||
|
||||
Be sure to [read the normal guide on how to report bugs](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md#how-do-i-report-bugs). In addition, provide these details:
|
||||
- Android version
|
||||
- device used (exact name)
|
||||
- screen size in pixels
|
||||
|
||||
**I will close all bug reports without this information without comment.** Gather all information, then make a new issue. It seems you can’t reopen a ticket if I close it, so this is necessary unfortunately.
|
||||
|
||||
|
||||
Can I share this?
|
||||
-----------------
|
||||
|
||||
You may, but only with technically skilled friends. If you do please point them to this page only. Reading these guides ensures only high quality bug reports are made which speeds up development. This is in everyone’s interest, as the time spent on working on bogus reports is not spent on improvements.
|
||||
|
||||
Once the app is ready for a broader audience, this will be made easier. For now it should only be used by developers who can help or send in improvements.
|
||||
|
||||
|
||||
How do I…?
|
||||
----------
|
||||
|
||||
- **Login:** on tablets, this should just work. On smartphones you’ll see a black screen with some blue lines. This is the normal Ingress login page and you need to scroll to see the login button.
|
||||
- **Clear Data/Cache:** Open app launcher and find the IITCM icon. Press-and-hold and then drag it to “App Info” on the top right of the screen. There’s a “clear data” and “clear cache” button.
|
||||
- **Logout:** Not possible from within the app. See *Clear Data/Cache* and use “clear data”.
|
||||
- **Reload:** Not possible from within the app. Instead, open your recent applications and force close IITCM. It should reload after restarting.
|
||||
- **“Your account has not been enabled to play Ingress“**: See *Reload*.
|
||||
- **Install:** You can find this out yourself. If you don’t know how, then please wait for a more polished version of IITCM.
|
||||
- **Update:** You can check if there’s a new APK build by looking at the [apk_version](https://github.com/breunigs/ingress-intel-total-conversion/raw/gh-pages/mobile/apk_version file)[.](https://mathphys.fsk.uni-heidelberg.de/~stefan/test/IngressIntelTC.apk) It contains the date of the last update. The app uses the latest IITC hourly build automatically. You may need to clear your cache to force a reload, see *Clear Data/Cache*. Also note that the dot after “apk_version” is the download link to the APK.
|
||||
|
||||
How does this basically work?
|
||||
-----------------------------
|
||||
|
||||
The Android App uses a WebView to render the normal web page. Some code is required to make this work like one would expect, but in a nutshell this is a webbrowser without URL bar. On page load, the app injects `bootstrap.js` which is a specialized loader. While it has some additional checks to make the boot process nicer on slower mobile phones but is mainly required to load vanilla IITC. It’s not possible to load IITC directly due to contraints defined by the injection method. After IITC is injected, it works the same way as on desktop browsers. Tablets are served the desktop version and apart from larger portals there is no change to the GUI. Smartphones execute the code in `code/smartphone.js` and load `smartphone.css`. This is required because their display is too small for the desktop version.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
If you want to debug the APK, I suggest [reading up on Google’s documentation](https://developer.android.com/index.html).
|
||||
|
||||
Debugging IITC(M) **after** it has booted is relatively easy: you can switch to the “debug” tab, which is a low end developer console. It renders all calls to `console.*`, so you can use it just like you expect. It may be easier to develop in a desktop browser. Set it up like explained [in the normal hacking guide](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md), but fake your user agent or modify the detection in `code/smartphone.js` and `main.js`. You don’t need to rebuild the APK to point it to your `iitc-test.user.js` file. Instead, modify `mobile/bootstrap.js` and add yourself with device ID and URL, then [send in a pull request](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md#sending-patches). The device ID is printed to the debug console on IITC boot.
|
||||
|
||||
Debugging IITC(M) **before** it has booted requires the Android Developer Tools. Connecting your device and running `adb logcat` should print the debug log to your computer until the low-end dev console mentioned above is available. You may need to root your device.
|
||||
|
||||
|
||||
Building the APK
|
||||
----------------
|
||||
|
||||
No idea. Please write docs and send patches.
|
||||
|
||||
|
||||
Download APK
|
||||
------------
|
||||
|
||||
Well, glad you read to the end. Enjoy and send patches, bug reports, postcards and love. (If you are wondering where the download link is, I’m wondering if you have actually read the page.)
|
||||
### [For developer docs, please see HACKING.md](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/mobile/HACKING.md)
|
||||
|
@ -1 +0,0 @@
|
||||
0.1-2013-02-23
|
59
mobile/bootstrap.js
vendored
@ -1,59 +0,0 @@
|
||||
var rebuidAttemptCount=0;
|
||||
var iitcReadyCount=0;
|
||||
var iitcURL;
|
||||
|
||||
function rebuildUI() {
|
||||
// this is sub-optimal, but we need a way to know if we're on a login page, or the real page.
|
||||
if(document.getElementById('dashboard_container')) {
|
||||
var dash = document.getElementById('dashboard_container');
|
||||
// dashboard is there, not conclusive
|
||||
if(dash.childNodes[0].innerHTML == 'Welcome to Ingress') {
|
||||
// not really 'ready', but the user needs the page for login purposes
|
||||
android.pageReady(1);
|
||||
return;
|
||||
} else if(!document.getElementById('map_canvas')) {
|
||||
// not loaded yet? we'll wait
|
||||
if(rebuidAttemptCount < 10) { // wait up to 5 seconds, then assume failure and show the page
|
||||
setTimeout(rebuildUI, 500);
|
||||
rebuidAttemptCount++;
|
||||
if(window.console) { console.log('Looking for Ingress Intel UI elements: ' + rebuidAttemptCount); }
|
||||
return;
|
||||
} else {
|
||||
if(window.console) { console.log('Something is wrong, flipping views'); }
|
||||
android.pageReady(1);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
window.UIDone = true;
|
||||
}
|
||||
|
||||
window.console.log(window.deviceID);
|
||||
window.console.log(navigator.userAgent);
|
||||
|
||||
switch(window.deviceID) {
|
||||
case '41ddb619ea1fe75a': // blakjakau - TABLET
|
||||
iitcURL = 'http://mathphys.fsk.uni-heidelberg.de:8000/test.js';
|
||||
break;
|
||||
|
||||
case 'f30c2cce86c1c7': // breunigs
|
||||
iitcURL = 'http://mathphys.fsk.uni-heidelberg.de:8000/test.js';
|
||||
break;
|
||||
|
||||
default:
|
||||
iitcURL = 'http://mathphys.fsk.uni-heidelberg.de:8000/test.js';
|
||||
}
|
||||
window.loadJS(iitcURL); // load iitc and let it do its thing.
|
||||
window.iitcReadyTimer = setInterval(function() {
|
||||
if(window.iitcLoaded == true || iitcReadyCount > 10) {
|
||||
//wait up to 10 seconds from calling iitc to fliping the webviews
|
||||
//if for some reason iitc isn't loading, the user will just get the vanila ingres.com/intel experience
|
||||
try {
|
||||
android.pageReady(1); // tell the app to flip the webviews
|
||||
clearInterval(window.iitcReadyTimer); // and we're done.
|
||||
} catch(e) { if(window.console) { console.log(e.message); } }
|
||||
}
|
||||
iitcReadyCount++;
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
rebuildUI();
|
92
mobile/build.xml
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="IITC_Mobile" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var.
|
||||
This must be done before we load project.properties since
|
||||
the proguard config can use sdk.dir -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
6
mobile/lint.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
<issue id="SetJavaScriptEnabled">
|
||||
<ignore path="src/com/cradle/ittc_mobile/iitc_webview.java" />
|
||||
</issue>
|
||||
</lint>
|
@ -3,9 +3,12 @@
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-10
|
||||
target=android-17
|
BIN
mobile/res/drawable-hdpi/ingress_iitc.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
mobile/res/drawable-mdpi/ingress_iitc.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
mobile/res/drawable-xhdpi/ingress_iitc.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
mobile/res/drawable-xxhdpi/ingress_iitc.png
Normal file
After Width: | Height: | Size: 21 KiB |
6
mobile/res/layout/activity_main.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.cradle.iitc_mobile.IITC_WebView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
/>
|
22
mobile/res/menu/main.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:id="@+id/reload_button"
|
||||
android:orderInCategory="100"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/reload"></item>
|
||||
|
||||
<item android:id="@+id/version_num"
|
||||
android:orderInCategory="100"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/version"></item>
|
||||
|
||||
<item android:id="@+id/cache_clear"
|
||||
android:orderInCategory="90"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/cache_clear"></item>
|
||||
|
||||
<item android:id="@+id/locate"
|
||||
android:orderInCategory="80"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/locate"></item>
|
||||
|
||||
</menu>
|
8
mobile/res/values-sw600dp/dimens.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Customize dimensions originally defined in res/values/dimens.xml (such as
|
||||
screen margins) for sw600dp devices (e.g. 7" tablets) here.
|
||||
-->
|
||||
|
||||
</resources>
|
9
mobile/res/values-sw720dp-land/dimens.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Customize dimensions originally defined in res/values/dimens.xml (such as
|
||||
screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
|
||||
-->
|
||||
<dimen name="activity_horizontal_margin">128dp</dimen>
|
||||
|
||||
</resources>
|
11
mobile/res/values-v11/styles.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme for API 11+. This theme completely replaces
|
||||
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||
<!-- API 11 theme customizations can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
12
mobile/res/values-v14/styles.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme for API 14+. This theme completely replaces
|
||||
AppBaseTheme from BOTH res/values/styles.xml and
|
||||
res/values-v11/styles.xml on API 14+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
|
||||
<!-- API 14 theme customizations can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
7
mobile/res/values/dimens.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<resources>
|
||||
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
||||
</resources>
|
11
mobile/res/values/strings.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">IITC mobile</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="reload">Reload IITC</string>
|
||||
<string name="version">Print Version</string>
|
||||
<string name="cache_clear">Clear Cache</string>
|
||||
<string name="locate">Get Location</string>
|
||||
|
||||
</resources>
|
20
mobile/res/values/styles.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||
<!--
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
-->
|
||||
</style>
|
||||
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -15,6 +15,7 @@ body {
|
||||
|
||||
#chatcontrols {
|
||||
height: 38px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* hide shrink button */
|
||||
@ -29,6 +30,9 @@ body {
|
||||
vertical-align: middle;
|
||||
line-height: 36px;
|
||||
text-decoration: none;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#chat {
|
||||
|
139
mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java
Normal file
@ -0,0 +1,139 @@
|
||||
package com.cradle.iitc_mobile;
|
||||
|
||||
import com.cradle.iitc_mobile.R;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class IITC_Mobile extends Activity {
|
||||
|
||||
private IITC_WebView iitc_view;
|
||||
private boolean back_button_pressed = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// we do not want to reload our page every time we switch orientations...
|
||||
// so restore state if activity was already created
|
||||
if(savedInstanceState != null) {
|
||||
((IITC_WebView)findViewById(R.id.webview)).restoreState(savedInstanceState);
|
||||
}
|
||||
else {
|
||||
// load new iitc web view with ingress intel page
|
||||
iitc_view= (IITC_WebView) findViewById(R.id.webview);
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getAction();
|
||||
if (Intent.ACTION_VIEW.equals(action)) {
|
||||
Uri uri = intent.getData();
|
||||
String url = uri.toString();
|
||||
Log.d("Intent received", "url: " + url);
|
||||
if (url.contains("ingress.com")) {
|
||||
Log.d("Intent received", "loading url...");
|
||||
iitc_view.loadUrl(url);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log.d("No Intent call", "loading https://www.ingress.com/intel");
|
||||
iitc_view.loadUrl("https://www.ingress.com/intel");
|
||||
}
|
||||
|
||||
// listen to touches (think we need this)
|
||||
iitc_view.setOnTouchListener(new OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
back_button_pressed = false;
|
||||
// return false to indicate, that we don't consumed this event. this leads
|
||||
// to the execution of our touch event
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// save instance state to avoid reloading on orientation change
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
iitc_view.saveState(outState);
|
||||
}
|
||||
|
||||
// we want a self defined behavior on resume
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
this.back_button_pressed = false;
|
||||
}
|
||||
|
||||
// we want a self defined behavior for the back button
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (this.back_button_pressed) {
|
||||
super.onBackPressed();
|
||||
return;
|
||||
}
|
||||
|
||||
iitc_view.loadUrl("javascript: window.goBack();");
|
||||
this.back_button_pressed = true;
|
||||
Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show();
|
||||
|
||||
// reset back button after 0.5 seconds
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
back_button_pressed=false;
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle item selection
|
||||
switch (item.getItemId()) {
|
||||
case R.id.reload_button:
|
||||
iitc_view.reload();
|
||||
return true;
|
||||
// print version number
|
||||
case R.id.version_num:
|
||||
PackageInfo pinfo;
|
||||
try {
|
||||
pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
|
||||
Toast.makeText(this, "Build version: " + pinfo.versionName, Toast.LENGTH_SHORT).show();
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
// clear cache
|
||||
case R.id.cache_clear:
|
||||
iitc_view.clearHistory();
|
||||
iitc_view.clearFormData();
|
||||
iitc_view.clearCache(true);
|
||||
return true;
|
||||
// get the users current location and focus it on map
|
||||
case R.id.locate:
|
||||
iitc_view.loadUrl("javascript: window.map.locate({setView : true, maxZoom: 13});");
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
58
mobile/src/com/cradle/iitc_mobile/IITC_WebView.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.cradle.iitc_mobile;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.GeolocationPermissions;
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
public class IITC_WebView extends WebView {
|
||||
|
||||
private WebSettings settings;
|
||||
private IITC_WebViewClient webclient;
|
||||
|
||||
// init web view
|
||||
private void iitc_init() {
|
||||
settings = this.getSettings();
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setDomStorageEnabled(true);
|
||||
settings.setAllowFileAccess(true);
|
||||
settings.setGeolocationEnabled(true);
|
||||
|
||||
// our webchromeclient should share geolocation with the iitc script
|
||||
// allow access by default
|
||||
this.setWebChromeClient(new WebChromeClient() {
|
||||
@Override
|
||||
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
|
||||
callback.invoke(origin, true, false);
|
||||
}
|
||||
});
|
||||
|
||||
webclient = new IITC_WebViewClient();
|
||||
this.setWebViewClient(webclient);
|
||||
}
|
||||
|
||||
// constructors -------------------------------------------------
|
||||
public IITC_WebView(Context context) {
|
||||
super(context);
|
||||
|
||||
iitc_init();
|
||||
}
|
||||
|
||||
public IITC_WebView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
iitc_init();
|
||||
}
|
||||
|
||||
public IITC_WebView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
iitc_init();
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
}
|
37
mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.cradle.iitc_mobile;
|
||||
|
||||
import android.net.http.SslError;
|
||||
import android.util.Log;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
public class IITC_WebViewClient extends WebViewClient {
|
||||
|
||||
// enable https
|
||||
@Override
|
||||
public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) {
|
||||
handler.proceed() ;
|
||||
};
|
||||
|
||||
// injecting IITC when page is loaded
|
||||
@Override
|
||||
public void onPageFinished(WebView web, String Url) {
|
||||
Log.d("loading finish", web.getUrl());
|
||||
if (web.getUrl().contains("ingress.com/intel") && !web.getUrl().contains("accounts")) {
|
||||
// first check for cookies, than inject javascript
|
||||
// this enables the user to login if necessary
|
||||
CookieManager cm = CookieManager.getInstance();
|
||||
final String cookie = cm.getCookie("https://www.ingress.com/intel");
|
||||
if(cookie != null) {
|
||||
web.loadUrl("javascript: (function() { "
|
||||
+ "var script=document.createElement('script');"
|
||||
+ "script.type='text/javascript';"
|
||||
+ "script.src='https://iitcserv.appspot.com/iitc-nightly/iitc-nightly-latest.user.js';"
|
||||
+ "document.getElementsByTagName('head').item(0).appendChild(script);"
|
||||
+ "})()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +1,9 @@
|
||||
Plugins
|
||||
=======
|
||||
USER DOCUMENTATION MOVED!
|
||||
=========================
|
||||
|
||||
Install
|
||||
-------
|
||||
Plugins are installed the same way the total conversion script is. Please see there for specific instructions for your browser.
|
||||
|
||||
|
||||
Available Plugins
|
||||
-----------------
|
||||
|
||||
- [**Compute AP Stats**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/compute-ap-stats.user.js) Shows the potential AP an agent could obtain by destroying and rebuilding all the portals in the current zoom area.
|
||||
- [**Draw Tools**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/draw-tools.user.js) allows to draw circles and lines on the map to aid you with planning your next big field. [View screenshot](http://breunigs.github.com/ingress-intel-total-conversion/screenshots/plugin_draw_tools.png)
|
||||
- [**Guess Player Level**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/guess-player-levels.user.js) looks for the highest placed resonator per player in the current view to guess the player level.
|
||||
- [**Highlight Weakened Portals**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weakness.user.js) fill portals with red to indicate portal's state of disrepair. The brighter the color the more attention needed (recharge, shields, resonators). A dashed portal means a resonator is missing. Red, needs energy and shields. Orange, only needs energy (either recharge or resonators). Yellow, only needs shields.
|
||||
- [**Max-Links**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/max-links.user.js) Calculates how to link the portals to create the maximum number of fields. [View screenshot](http://breunigs.github.com/ingress-intel-total-conversion/screenshots/plugin_max_links.png)
|
||||
- [**Player Tracker**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/player-tracker.user.js) Draws trails for user actions in the last hour. At the last known location there’s a tooltip that shows the data in a table. [View screenshot](http://breunigs.github.com/ingress-intel-total-conversion/screenshots/plugin_player_tracker.png).
|
||||
- [**Render Limit Increase**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/render-limit-increase.user.js) increases render limits. Good for high density areas (e.g. London, UK) and faster PCs.
|
||||
- [**Resonator Display Zoom Level Decrease**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/resonator-display-zoom-level-decrease.user.js) Resonator start displaying earlier.
|
||||
- [**Resonator Energy in Portal Detail**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/reso-energy-pct-in-portal-detail.user.js) Resonator energy in percent is displayed in the portal detals.
|
||||
- [**Scale Bar**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/scale-bar.user.js) Shows a scale bar in the top left corner. [View screenshot](http://breunigs.github.com/ingress-intel-total-conversion/scre
|
||||
enshots/plugin_scale_bar.png)
|
||||
- [**Show Portal Address**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-address.user.js) Shows portal address in the side panel.
|
||||
|
||||
### available only with the development version
|
||||
- [**Scoreboard**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/scoreboard.user.js) Adds a scoreboard popup (link near bottom of the side panel) so you better see your local impact on the game.
|
||||
|
||||
[Read HACKING.md file](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md#hacking) to learn how to build the development version yourself. If **and only if** [you have read how to report bugs](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/HACKING.md#how-do-i-report-bugs), you may beta test the [nightly](https://www.dropbox.com/sh/lt9p0s40kt3cs6m/3xzpyiVBnF) version.
|
||||
[The plugins list has been moved to the wiki. Please see there!](https://github.com/breunigs/ingress-intel-total-conversion/wiki/Plugins)
|
||||
|
||||
What follows is developer documentation only.
|
||||
|
||||
|
||||
|
||||
|
@ -43,7 +43,7 @@ window.plugin.guessPlayerLevels.setLevelTitle = function(dom) {
|
||||
var text;
|
||||
if (nick in playersNamed) {
|
||||
text = 'Min player level: ' + playersNamed[nick];
|
||||
if(playersNamed[nick] === window.MAX_XM_PER_LEVEL - 1) text += ' (guessed)';
|
||||
if(playersNamed[nick] < window.MAX_XM_PER_LEVEL.length - 1) text += ' (guessed)';
|
||||
} else {
|
||||
text = 'Min player level unknown';
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @id iitc-plugin-player-tracker@breunigs
|
||||
// @name iitc: player tracker
|
||||
// @version 0.6.1
|
||||
// @version 0.7
|
||||
// @namespace https://github.com/breunigs/ingress-intel-total-conversion
|
||||
// @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/player-tracker.user.js
|
||||
// @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/player-tracker.user.js
|
||||
@ -80,7 +80,8 @@ window.plugin.playerTracker.processNewData = function(data) {
|
||||
// field was originally created. Therefore it’s not clear which
|
||||
// portal the player is at, so ignore it.
|
||||
if(markup[1].plain.indexOf('destroyed the Link') !== -1
|
||||
|| markup[1].plain.indexOf('destroyed a Control Field') !== -1) {
|
||||
|| markup[1].plain.indexOf('destroyed a Control Field') !== -1
|
||||
|| markup[1].plain.indexOf('Your Link') !== -1) {
|
||||
skipThisMessage = true;
|
||||
return false;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @id iitc-plugin-show-portal-weakness@vita10gy
|
||||
// @name iitc: show portal weakness
|
||||
// @version 0.5
|
||||
// @version 0.6
|
||||
// @namespace https://github.com/breunigs/ingress-intel-total-conversion
|
||||
// @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weakness.user.js
|
||||
// @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weakness.user.js
|
||||
@ -35,7 +35,7 @@ window.plugin.portalWeakness.portalAdded = function(data) {
|
||||
$.each(d.portalV2.linkedModArray, function(ind, mod) {
|
||||
if(mod === null) {
|
||||
missing_shields++;
|
||||
portal_weakness += .08;
|
||||
portal_weakness += .03;
|
||||
}
|
||||
});
|
||||
//Ding the portal for every missing resonator.
|
||||
|
BIN
screenshots/apk_qr_code.png
Normal file
After Width: | Height: | Size: 429 B |
BIN
screenshots/mobile_chat.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
screenshots/mobile_layer_chooser.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
screenshots/mobile_map.png
Normal file
After Width: | Height: | Size: 204 KiB |
BIN
screenshots/mobile_portal_view.png
Normal file
After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 71 KiB |
13
style.css
@ -3,6 +3,7 @@
|
||||
html, body, #map {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden; /* workaround for #373 */
|
||||
}
|
||||
|
||||
body {
|
||||
@ -748,3 +749,15 @@ td {
|
||||
td + td {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
/* redeem results *****************************************************/
|
||||
.redeem-result {
|
||||
font-size: 14px;
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.redeem-result tr > td:first-child {
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
}
|
||||
|
56
tools/README.md
Normal file
@ -0,0 +1,56 @@
|
||||
These files are stored here as reference and backup for me. You likely
|
||||
won’t need them, as the script runs on one of my servers and handles all
|
||||
the building for you.
|
||||
|
||||
Still, here’s how it goes down:
|
||||
- `iitc-nightly.sh` is run by a cronjob. Config: `50 1 * * * /home/pi/iitc-nightly.sh > /dev/null`
|
||||
- the ZSH script grabs the latest IITC tarball and extracts it
|
||||
- it gets the latest revision sha1
|
||||
- builds
|
||||
- uploads to Dropbox using [Dropbox-Up](https://github.com/andreafabrizi/Dropbox-Uploader)
|
||||
- wild copy magic to get the correct folder structure for app engine
|
||||
- uploading to app engine using Google’s appcfg.sh script (available [in the Java AppEngine SDK](https://developers.google.com/appengine/downloads))
|
||||
|
||||
|
||||
You don’t need the whole app engine folder, only some files *and folders*.
|
||||
The directory structure is shown below where `./appenginesmall/bin/appcfg.sh update war`
|
||||
will update all files in `war/` without `war/WEB-INF`.
|
||||
|
||||
```
|
||||
~/iitc-appengine $ tree
|
||||
.
|
||||
├── appenginesmall
|
||||
│ ├── bin
|
||||
│ │ └── appcfg.sh
|
||||
│ ├── config
|
||||
│ │ └── sdk
|
||||
│ │ └── logging.properties
|
||||
│ ├── docs
|
||||
│ │ └── appengine-web.xsd
|
||||
│ └── lib
|
||||
│ ├── appengine-tools-api.jar
|
||||
│ ├── impl
|
||||
│ │ └── agent
|
||||
│ ├── opt
|
||||
│ │ └── tools
|
||||
│ │ └── appengine-local-endpoints
|
||||
│ │ └── v1
|
||||
│ ├── shared
|
||||
│ │ └── jsp
|
||||
│ ├── tools
|
||||
│ │ └── jsp
|
||||
│ └── user
|
||||
└── war
|
||||
├── dist
|
||||
│ ├── …
|
||||
├── iitc-nightly
|
||||
│ ├── iitc-nightly-latest.user.js
|
||||
│ └── …
|
||||
├── images
|
||||
│ ├── …
|
||||
├── screenshots
|
||||
│ ├── …
|
||||
└── WEB-INF
|
||||
├── appengine-web.xml
|
||||
└── web.xml
|
||||
```
|
14
tools/appengine/war/WEB-INF/appengine-web.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||
<application>iitcserv</application>
|
||||
<version>1</version>
|
||||
|
||||
<static-files>
|
||||
<include path="/**.png" expiration="7d"/>
|
||||
<include path="/**.css" expiration="2d"/>
|
||||
<include path="/**.js" expiration="7d"/>
|
||||
<include path="/iitc-nightly/iitc-nightly-latest.user.js.js" expiration="12h"/>
|
||||
<include path="/iitc-nightly/**"/>
|
||||
<include path="/mobile/**"/>
|
||||
</static-files>
|
||||
<threadsafe>true</threadsafe>
|
||||
</appengine-web-app>
|
27
tools/appengine/war/WEB-INF/web.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
|
||||
<context-param>
|
||||
<param-name>org.mortbay.jetty.servlet.Default.dirAllowed</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>default</servlet-name>
|
||||
<servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>acceptRanges</param-name><param-value>true</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>dirAllowed</param-name><param-value>true</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>0</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>/iitc-nightly/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>/mobile/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
@ -1,15 +1,30 @@
|
||||
#!/bin/sh
|
||||
#!/bin/zsh
|
||||
|
||||
GIT="git://github.com/breunigs/ingress-intel-total-conversion.git"
|
||||
URL="https://nodeload.github.com/breunigs/ingress-intel-total-conversion/tar.gz/gh-pages"
|
||||
PTH="ingress-intel-total-conversion-gh-pages"
|
||||
|
||||
set -e
|
||||
|
||||
cd /tmp
|
||||
rm -rf ingress-intel-total-conversion
|
||||
git clone --depth=1 git://github.com/breunigs/ingress-intel-total-conversion.git
|
||||
cd ingress-intel-total-conversion
|
||||
rm -rf $PTH
|
||||
wget -q -O - $URL | (cd /tmp && tar xfz -)
|
||||
cd $PTH
|
||||
./build.py
|
||||
|
||||
date=$(date +"%Y-%m-%d")
|
||||
commit=$(git rev-parse HEAD | head -c 10)
|
||||
|
||||
commit=$(git ls-remote --heads $GIT | head -c 10)
|
||||
# https://github.com/andreafabrizi/Dropbox-Uploader
|
||||
dropbox-up upload iitc-debug.user.js iitc-nightly/iitc-nightly-$date-$commit.user.js
|
||||
/opt/dropbox-up upload iitc-debug.user.js iitc-nightly/iitc-nightly-$date-$commit.user.js
|
||||
/opt/dropbox-up upload iitc-debug.user.js iitc-nightly/iitc-nightly-latest.user.js
|
||||
|
||||
cp iitc-debug.user.js /home/pi/iitc-appengine/war/iitc-nightly/iitc-nightly-$date-$commit.user.js
|
||||
cp iitc-debug.user.js /home/pi/iitc-appengine/war/iitc-nightly/iitc-nightly-latest.user.js
|
||||
mv screenshots/* /home/pi/iitc-appengine/war/screenshots
|
||||
mv images/* /home/pi/iitc-appengine/war/images
|
||||
mv dist/images/* /home/pi/iitc-appengine/war/dist/images/
|
||||
rmdir dist/images
|
||||
mv dist/* /home/pi/iitc-appengine/war/dist/
|
||||
cd /home/pi/iitc-appengine/
|
||||
rm **/*@* # not supported by app engine
|
||||
./appenginesmall/bin/appcfg.sh update war
|
||||
|