This commit is contained in:
Jon Atkins 2014-02-12 22:32:09 +00:00
commit fcbce165b9
14 changed files with 556 additions and 95 deletions

View File

@ -72,6 +72,45 @@
<data android:scheme="geo"/>
</intent-filter>
<!-- Handles external user plugins -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:mimeType="application/x-javascript" />
<data android:mimeType="text/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="*"
android:scheme="file"
android:pathPattern=".*\\.user.js"/>
<data
android:host="*"
android:scheme="content"
android:pathPattern=".*\\.user.js"/>
<data
android:host="*"
android:scheme="http"
android:pathPattern=".*\\.user.js"/>
<data
android:host="*"
android:scheme="https"
android:pathPattern=".*\\.user.js"/>
</intent-filter>
<!-- Points to searchable meta data. -->
<meta-data
android:name="android.app.searchable"

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_plugins_add"
android:icon="@drawable/ic_action_new"
android:orderInCategory="10"
android:showAsAction="ifRoom|collapseActionView"
android:title="@string/menu_plugins_add"/>
</menu>

View File

@ -86,9 +86,8 @@
<string name="notice_extplugins">
<![CDATA[Hint:<br><br>
IITC Mobile is able to load external plugins too!<br><br>
• create <b>%1$s</b><br>
• move *.user.js files there<br>
• plugins should be listed above the official plugins]]>
Add them by clicking the (+) icon at the top right.
The plugin files have to end with \'.user.js\' and are copied to <b>%1$s</b><br>]]>
</string>
<string name="notice_sharing">
<![CDATA[With <em>Share portal</em> you can:<br>
@ -162,6 +161,7 @@
<string name="menu_clear_cookies">Clear Cookies</string>
<string name="menu_search">Search</string>
<string name="menu_debug">Debug</string>
<string name="menu_plugins_add">Add external plugins</string>
<string name="choose_account_to_login">Choose account to login</string>
<string name="login_failed">Login failed.</string>
<string name="search_hint">Search Locations</string>
@ -177,4 +177,9 @@
<string name="label_base_layer">Base Layer</string>
<string name="label_overlay_layers">Overlay Layers</string>
<string name="install_dialog_top">Install external plugin?</string>
<string name="install_dialog_msg">
IITCm was requested to install the following plugin:\n\n%1$s\n\nDo you want to proceed?
</string>
</resources>

View File

@ -1,7 +1,9 @@
package com.cradle.iitc_mobile;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
@ -22,11 +24,14 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
@ -118,15 +123,17 @@ public class IITC_FileManager {
}
private final AssetManager mAssetManager;
private final IITC_Mobile mIitc;
private final Activity mActivity;
private final String mIitcPath;
private final SharedPreferences mPrefs;
public static final String PLUGINS_PATH = Environment.getExternalStorageDirectory().getPath()
+ "/IITC_Mobile/plugins/";
public IITC_FileManager(final IITC_Mobile iitc) {
mIitc = iitc;
mIitcPath = Environment.getExternalStorageDirectory().getPath() + "/IITC_Mobile/";
mPrefs = PreferenceManager.getDefaultSharedPreferences(iitc);
mAssetManager = mIitc.getAssets();
public IITC_FileManager(final Activity activity) {
mActivity = activity;
mIitcPath = Environment.getExternalStorageDirectory().getPath() + "/Activity/";
mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
mAssetManager = mActivity.getAssets();
}
private InputStream getAssetFile(final String filename) throws IOException {
@ -135,10 +142,10 @@ public class IITC_FileManager {
try {
return new FileInputStream(file);
} catch (final FileNotFoundException e) {
mIitc.runOnUiThread(new Runnable() {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(mIitc, "File " + mIitcPath +
Toast.makeText(mActivity, "File " + mIitcPath +
"dev/" + filename + " not found. " +
"Disable developer mode or add iitc files to the dev folder.",
Toast.LENGTH_SHORT).show();
@ -233,6 +240,73 @@ public class IITC_FileManager {
return EMPTY;
}
public void installPlugin(final String uri, final boolean invalidateHeaders) {
if (uri != null) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mActivity);
// set title
alertDialogBuilder.setTitle(mActivity.getString(R.string.install_dialog_top));
// set dialog message
String text = mActivity.getString(R.string.install_dialog_msg);
text = String.format(text, uri);
alertDialogBuilder
.setMessage(text)
.setCancelable(true)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
copyPlugin(uri, invalidateHeaders);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
}
private void copyPlugin(final String uri, final boolean invalidateHeaders) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
final URL url = new URL(uri);
final URLConnection conn = url.openConnection();
final String fileName = uri.substring( uri.lastIndexOf('/')+1, uri.length() );
final InputStream is = conn.getInputStream();
// create IITCm external plugins directory if it doesn't already exist
final File pluginsDirectory = new File(PLUGINS_PATH);
pluginsDirectory.mkdirs();
// create in and out streams and copy plugin
File outFile = new File(pluginsDirectory + "/" + fileName);
OutputStream os = new FileOutputStream(outFile);
IITC_FileManager.copyStream(is, os, true);
} catch (IOException e) {
Log.w(e);
}
}
});
thread.start();
if (invalidateHeaders) {
try {
thread.join();
((IITC_PluginPreferenceActivity) mActivity).invalidateHeaders();
} catch (InterruptedException e) {
Log.w(e);
}
}
}
private class FileRequest extends WebResourceResponse implements ResponseHandler, Runnable {
private Intent mData;
private final String mFunctionName;
@ -258,16 +332,18 @@ public class IITC_FileManager {
target.addCategory(Intent.CATEGORY_OPENABLE);
try {
mIitc.startActivityForResult(Intent.createChooser(target, "Choose file"), this);
final IITC_Mobile iitc = (IITC_Mobile) mActivity;
iitc.startActivityForResult(Intent.createChooser(target, "Choose file"), this);
} catch (final ActivityNotFoundException e) {
Toast.makeText(mIitc, "No activity to select a file found." +
Toast.makeText(mActivity, "No activity to select a file found." +
"Please install a file browser of your choice!", Toast.LENGTH_LONG).show();
}
}
@Override
public void onActivityResult(final int resultCode, final Intent data) {
mIitc.deleteResponseHandler(this); // to enable garbage collection
final IITC_Mobile iitc = (IITC_Mobile) mActivity;
iitc.deleteResponseHandler(this); // to enable garbage collection
mResultCode = resultCode;
mData = data;

View File

@ -228,6 +228,13 @@ public class IITC_Mobile extends Activity
.show();
}
}
if (uri.getPath().endsWith(".user.js")) {
final Intent prefIntent = new Intent(this, IITC_PluginPreferenceActivity.class);
prefIntent.putExtra("url", uri.toString());
startActivity(prefIntent);
// TODO receive intent, start dialog if user want to install $plugin, reload IITC
}
}
if (Intent.ACTION_SEARCH.equals(action)) {

View File

@ -1,18 +1,21 @@
package com.cradle.iitc_mobile;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceActivity;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
import android.widget.Toast;
import com.cradle.iitc_mobile.fragments.PluginsFragment;
@ -29,6 +32,8 @@ import java.util.TreeMap;
public class IITC_PluginPreferenceActivity extends PreferenceActivity {
private final static int COPY_PLUGIN_REQUEST = 1;
private List<Header> mHeaders;
// we use a tree map to have a map with alphabetical order
// don't initialize the asset plugin map, because it tells us if the settings are started the first time
@ -39,6 +44,8 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
new TreeMap<String, ArrayList<IITC_PluginPreference>>();
private static int mDeletedPlugins = 0;
private IITC_FileManager mFileManager;
@Override
public void setListAdapter(final ListAdapter adapter) {
if (adapter == null) {
@ -78,6 +85,13 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
getIntent()
.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, PluginsFragment.class.getName());
}
mFileManager = new IITC_FileManager(this);
final String uri = getIntent().getStringExtra("url");
if (uri != null) {
mFileManager.installPlugin(uri, true);
}
super.onCreate(savedInstanceState);
}
@ -103,17 +117,53 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.plugins, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home: // exit settings when home button (iitc icon) is pressed
onBackPressed();
return true;
case R.id.menu_plugins_add:
// create the chooser Intent
final Intent target = new Intent(Intent.ACTION_GET_CONTENT);
// iitcm only parses *.user.js scripts
target.setType("file/*");
target.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(Intent.createChooser(target, "Choose file"), COPY_PLUGIN_REQUEST);
} catch (final ActivityNotFoundException e) {
Toast.makeText(this, "No activity to select a file found." +
"Please install a file browser of your choice!", Toast.LENGTH_LONG).show();
}
default:
return super.onOptionsItemSelected(item);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode) {
case COPY_PLUGIN_REQUEST:
if (data != null && data.getData() != null) {
String filePath = data.getData().getPath();
mFileManager.installPlugin("file://" + filePath, true);
return;
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
@Override
protected boolean isValidFragment(final String s) {
return true;
@ -141,9 +191,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
}
private File[] getUserPlugins() {
final String iitc_path = Environment.getExternalStorageDirectory().getPath()
+ "/IITC_Mobile/";
final File directory = new File(iitc_path + "plugins/");
final File directory = new File(IITC_FileManager.PLUGINS_PATH);
File[] files = directory.listFiles();
if (files == null) {
files = new File[0];
@ -164,6 +212,8 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
if ((userPlugins.length + officialPlugins.length) != (numPlugins + mDeletedPlugins)) {
Log.d("new or less plugins found since last start, rebuild preferences");
sAssetPlugins.clear();
sUserPlugins.clear();
mDeletedPlugins = 0;
setUpPluginPreferenceScreen();
}
}

View File

@ -2,7 +2,7 @@
// @id iitc-plugin-bookmarks@ZasoGD
// @name IITC plugin: Bookmarks for maps and portals
// @category Controls
// @version 0.2.7.@@DATETIMEVERSION@@
// @version 0.2.8.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -151,18 +151,11 @@
}
if(newStatus === 1) {
$('#bookmarksBox').show();
$('#bkmrksTrigger').hide();
$('#bookmarksBox').css('height', 'auto');
$('#bkmrksTrigger').css('height', '0');
} else {
$('#bookmarksBox').hide();
$('#bkmrksTrigger').show();
}
if(window.plugin.bookmarks.isSmart) {
var button = $('#bkmrksTrigger');
button.toggleClass('open');
if(button.hasClass('open')) { button.text('[-] Bookmarks'); }
else{ button.text('[+] Bookmarks'); }
$('#bkmrksTrigger').css('height', '64px');
$('#bookmarksBox').css('height', '0');
}
window.plugin.bookmarks.statusBox['show'] = newStatus;
@ -433,6 +426,11 @@
}
}
window.plugin.bookmarks.deleteMode = function() {
$('#bookmarksBox').toggleClass('deleteMode');
}
/***************************************************************************************************************************************************************/
// Saved the new sort of the folders (in the localStorage)
@ -489,6 +487,7 @@
items:"li.bookmarkFolder:not(.othersBookmarks)",
handle:".bookmarksAnchor",
placeholder:"sortable-placeholder",
helper:'clone', // fix accidental click in firefox
forcePlaceholderSize:true,
update:function(event, ui) {
var typeList = $('#'+ui.item.context.id).parent().parent('.bookmarkList').attr('id');
@ -501,6 +500,7 @@
connectWith:".bookmarkList ul ul",
handle:".bookmarksLink",
placeholder:"sortable-placeholder",
helper:'clone', // fix accidental click in firefox
forcePlaceholderSize:true,
update:function(event, ui) {
var typeList = $('#'+ui.item.context.id).parent().parent().parent().parent('.bookmarkList').attr('id');
@ -548,17 +548,22 @@
window.plugin.bookmarks.optPaste = function() {
var promptAction = prompt('Press CTRL+V to paste it.', '');
if(promptAction !== null && promptAction !== '') {
localStorage[window.plugin.bookmarks.KEY_STORAGE] = promptAction;
window.plugin.bookmarks.refreshBkmrks();
window.runHooks('pluginBkmrksEdit', {"target": "all", "action": "import"});
console.log('BOOKMARKS: reset and imported bookmarks');
window.plugin.bookmarks.optAlert('Successful. ');
try {
localStorage[window.plugin.bookmarks.KEY_STORAGE] = promptAction;
window.plugin.bookmarks.refreshBkmrks();
window.runHooks('pluginBkmrksEdit', {"target": "all", "action": "import"});
console.log('BOOKMARKS: reset and imported bookmarks');
window.plugin.bookmarks.optAlert('Successful. ');
} catch(e) {
console.warn('BOOKMARKS: failed to import data: '+e);
window.plugin.bookmarks.optAlert('<span style="color: #f88">Import failed </span>');
}
}
}
window.plugin.bookmarks.optReset = function() {
var promptAction = prompt('All bookmarks will be deleted. Are you sure? [Y/N]', '');
if(promptAction !== null && (promptAction === 'Y' || promptAction === 'y')) {
var promptAction = confirm('All bookmarks will be deleted. Are you sure?', '');
if(promptAction) {
delete localStorage[window.plugin.bookmarks.KEY_STORAGE];
window.plugin.bookmarks.createStorage();
window.plugin.bookmarks.loadStorage();
@ -618,6 +623,8 @@
if(latlngs.length >= 2 && latlngs.length <= 3) {
// TODO: add an API to draw-tools rather than assuming things about it's internals
var newItem;
window.plugin.drawTools.setOptions();
if(latlngs.length == 2) {
newItem = L.geodesicPolyline(latlngs, window.plugin.drawTools.lineOptions);
} else {
@ -885,6 +892,7 @@
+'<div id="topBar">'
+'<a id="bookmarksMin" class="btn" onclick="window.plugin.bookmarks.switchStatusBkmrksBox(0);return false;" title="Minimize">-</a>'
+'<div class="handle">...</div>'
+'<a id="bookmarksDel" class="btn" onclick="window.plugin.bookmarks.deleteMode();return false;" title="Show/Hide \'X\' button">Show/Hide "X" button</a>'
+'</div>'
+'<div id="bookmarksTypeBar">'
+'<h5 class="bkmrk_maps current" onclick="window.plugin.bookmarks.switchPageBkmrksBox(this, 0);return false">Maps</h5>'
@ -904,6 +912,7 @@
+'<a class="newFolder" onclick="window.plugin.bookmarks.addElement(this, \'folder\');return false;">+ Folder</a>'
+'</div>'
+'</div>'
+'<div style="border-bottom-width:1px;"></div>'
+'</div>';
plugin.bookmarks.htmlDisabledMessage = '<div title="Your browser do not support localStorage">Plugin Bookmarks disabled*.</div>';

View File

@ -9,13 +9,20 @@
line-height:22px;
text-indent:0;
text-decoration:none;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
#bookmarksBox{
display:block;
position:absolute !important;
z-index:4001;
top:100px;
left:100px;
width:231px;
height:auto;
overflow:hidden;
}
#bookmarksBox .addForm,
#bookmarksBox #bookmarksTypeBar,
@ -25,33 +32,40 @@
color:#fff;
font-size:14px;
}
#bookmarksBox #topBar,
#bookmarksBox #topBar *{
#bookmarksBox #topBar{
height:15px !important;
}
#bookmarksBox #topBar *{
height: 14px !important;
}
#bookmarksBox #topBar *{
float:left !important;
}
#bookmarksBox .handle{
text-indent:-20px;
width:209px;
width:80%;
text-align:center;
color:#fff;
line-height:8px;
line-height:6px;
cursor:move;
}
#bookmarksBox #topBar .btn{
display:block;
width:19px;
width:10%;
cursor:pointer;
color:#20a8b1;
}
#bookmarksBox #topBar #bookmarksMin{
font-weight:bold;
text-align:center;
line-height:14px;
line-height:13px;
font-size:18px;
}
#bookmarksBox #topBar #bookmarksDel{
overflow:hidden;
text-indent:-999px;
background:#B42E2E;
}
#bookmarksBox #topBar #bookmarksMin:hover{
color:#ffce00;
}
@ -59,8 +73,9 @@
clear:both;
}
#bookmarksBox h5{
padding:4px 0;
width:114px;
padding:4px 0 23px;
width:50%;
height:93px !important;
text-align:center;
color:#788;
}
@ -73,9 +88,8 @@
color:#ffce00;
background:rgba(0,0,0,0);
}
#bookmarksBox #topBar .btn,
#bookmarksBox #topBar,
#bookmarksBox .addForm,
#bookmarksBox .handle,
#bookmarksBox #bookmarksTypeBar,
#bookmarksBox .bookmarkList li.bookmarksEmpty,
#bookmarksBox .bookmarkList li.bkmrk a,
@ -90,16 +104,16 @@
#bookmarksBox .addForm *{
display:block;
float:left;
padding:4px 8px 3px;
height:28px !important;
}
#bookmarksBox .addForm a{
cursor:pointer;
color:#20a8b1;
font-size:12px;
width:65px;
width:35%;
text-align:center;
line-height:20px;
padding:4px 0 3px;
padding:4px 0 23px;
}
#bookmarksBox .addForm a:hover{
background:#ffce00;
@ -109,15 +123,19 @@
#bookmarksBox .addForm input{
font-size:11px !important;
color:#ffce00;
width:81px;
line-height:11px;
height:28px;
padding:4px 8px 1px;
line-height:12px;
font-size:12px;
-webkit-box-sizing:content-box;
-moz-box-sizing:content-box;
box-sizing:content-box;
}
#bookmarksBox #bkmrk_portals .addForm input{
width:147px;
width:65%;
}
#bookmarksBox #bkmrk_maps .addForm input{
width:42%;
}
#bookmarksBox #bkmrk_maps .addForm a{
width:29%;
}
#bookmarksBox .addForm input:hover,
#bookmarksBox .addForm input:focus{
@ -125,11 +143,12 @@
background:rgba(0,0,0,.6);
}
#bookmarksBox .bookmarkList > ul{
width:231px;
clear:both;
list-style-type:none;
color:#fff;
overflow:hidden;
overflow-y:auto;
max-height:580px;
}
#bookmarksBox .sortable-placeholder{
background:rgba(8,48,78,.55);
@ -161,12 +180,12 @@
color:#eee;
}
#bookmarksBox ul .bookmarksRemoveFrom{
width:19px;
width:10%;
text-align:center;
color:#fff;
}
#bookmarksBox ul .bookmarksLink{
width:171px;
width:90%;
padding:0 10px 0 8px;
color:#ffce00;
}
@ -174,7 +193,7 @@
color:#03fe03;
}
#bookmarksBox ul .othersBookmarks .bookmarksLink{
width:190px;
width:90%;
}
#bookmarksBox ul .bookmarksLink:hover{
color:#03fe03;
@ -183,6 +202,8 @@
color:#fff;
background:#e22 !important;
}
/*---- UI border -----*/
#bookmarksBox,
#bookmarksBox *{
border-color:#20a8b1;
@ -193,40 +214,44 @@
#bookmarksBox ul .bookmarkFolder{
border-top-width:1px;
}
#bookmarksBox #topBar,
#bookmarksBox #bookmarksTypeBar,
#bookmarksBox .addForm,
#bookmarksBox ul .bookmarkFolder .folderLabel,
#bookmarksBox ul li.bkmrk{
#bookmarksBox ul li.bkmrk a {
border-bottom-width:1px;
}
#bookmarksBox ul .bookmarkFolder,
#bookmarksBox ul .bookmarksRemoveFrom{
#bookmarksBox ul .bookmarkFolder{
border-right-width:1px;
border-left-width:1px;
}
#bookmarksBox #topBar *,
#bookmarksBox #bookmarksTypeBar *,
#bookmarksBox .addForm *{
#bookmarksBox .addForm *,
#bookmarksBox ul li.bkmrk{
border-left-width:1px;
}
#bookmarksBox #topBar,
#bookmarksBox #bookmarksTypeBar,
#bookmarksBox .addForm{
#bookmarksBox .addForm,
#bookmarksBox ul .bookmarksRemoveFrom{
border-right-width:1px;
}
#bookmarksBox ul .othersBookmarks .bookmarksRemoveFrom,
#bookmarksBox ul .bookmarkFolder.othersBookmarks li.bkmrk,
#bookmarksBox ul .bookmarkFolder .folderLabel .bookmarksRemoveFrom{
border-left-width:0;
}
#bkmrksTrigger{
display:none;
display:block !important;
position:absolute;
overflow:hidden;
top:0;
left:277px;
width:47px;
margin-top:-36px;
height:64px;
height:0;
cursor:pointer;
z-index:2999;
background-position:center bottom;
@ -272,17 +297,25 @@
}
#bookmarksBox .bookmarkList .bkmrk.ui-sortable-helper{
border-right-width:1px;
border-left-width:1px;
border-left-width:1px !important;
}
#bookmarksBox .bookmarkList ul li ul li.sortable-placeholder{
height:23px;
box-shadow:inset 0 -1px 0 #20a8b1,inset 1px 0 0 #20a8b1;
}
#bookmarksBox .bookmarkList ul li.bookmarkFolder.ui-sortable-helper,
#bookmarksBox .bookmarkList ul li.othersBookmarks ul,
#bookmarksBox .bookmarkList ul li.othersBookmarks ul li.sortable-placeholder{
box-shadow:inset 0 -1px 0 #20a8b1;
}
#bookmarksBox #topBar #bookmarksDel,
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel:hover .bookmarksRemoveFrom,
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel:hover .bookmarksAnchor{
border-bottom-width:1px;
}
/*---------*/
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span,
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel > span,
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel > span > span,
@ -304,7 +337,7 @@
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor{
line-height:25px;
color:#fff;
width:209px;
width:90%;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span{
float:left;
@ -336,6 +369,7 @@
#bookmarksBox .bookmarkList .bookmarkFolder.open .folderLabel > span,
#bookmarksBox .bookmarkList .bookmarkFolder.open .folderLabel > span > span{
display:block;
display:none;
}
#bookmarksBox .bookmarkList .bookmarkFolder.open .folderLabel:hover > span > span{
border-color:transparent #036 transparent transparent;
@ -345,7 +379,7 @@
}
#bookmarksBox .bookmarkList .bookmarkFolder ul{
display:none;
margin-left:19px;
margin-left:10%;
}
#bookmarksBox .bookmarkList .bookmarkFolder.open ul{
display:block;
@ -355,6 +389,26 @@
margin-left:0;
}
/*---- Width for deleteMode -----*/
#bookmarksBox .bookmarksRemoveFrom{
display:none !important;
}
#bookmarksBox.deleteMode .bookmarksRemoveFrom{
display:block !important;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor,
#bookmarksBox ul .bookmarksLink,
#bookmarksBox ul .othersBookmarks .bookmarksLink{
width:100% !important;
}
#bookmarksBox.deleteMode .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor,
#bookmarksBox.deleteMode ul .bookmarksLink,
#bookmarksBox.deleteMode ul .othersBookmarks .bookmarksLink{
width:90% !important;
}
/**********************************************
MOBILE
**********************************************/
@ -367,7 +421,8 @@
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
background: transparent !important;;
background: transparent !important;
overflow:auto !important;
}
#bookmarksBox.mobile .bookmarkList ul,
#bookmarksBox.mobile .bookmarkList ul li,
@ -380,14 +435,27 @@
box-shadow:none !important;
border-width:0 !important;
}
#bookmarksBox.mobile #topBar{
#bookmarksBox.mobile #topBar #bookmarksMin,
#bookmarksBox.mobile #topBar .handle{
display:none !important;
}
#bookmarksBox.mobile #topBar #bookmarksDel{
width:100%;
height:34px !important;
font-size:13px;
color:#fff;
font-weight:normal;
padding-top:11px;
text-indent:0;
}
#bookmarksBox.mobile #bookmarksTypeBar h5{
cursor:pointer;
text-align:center;
float:left;
width:50%;
height:auto !important;
padding:7px 0;
}
#bookmarksBox.mobile #bookmarksTypeBar h5.current{
@ -413,14 +481,14 @@
#bookmarksBox.mobile .bookmarkList li.bookmarkFolder a.bookmarksRemoveFrom,
#bookmarksBox.mobile .bookmarkList li.bkmrk a.bookmarksRemoveFrom{
box-shadow:inset 0 1px 0 #20a8b1,inset -1px 0 0 #20a8b1 !important;
width:15%;
width:10%;
background:none !important;
}
#bookmarksBox.mobile .bookmarkList li.bookmarkFolder a.bookmarksAnchor,
#bookmarksBox.mobile .bookmarkList li.bkmrk a.bookmarksLink{
text-indent:10px;
width:85%;
height:21px;
height:36px;
line-height:24px;
overflow:hidden;
}
#bookmarksBox.mobile .bookmarkList ul li.bookmarkFolder ul{
@ -428,7 +496,6 @@
}
#bookmarksBox.mobile .bookmarkList > ul{
border-bottom:1px solid #20a8b1 !important;
border-right:1px solid #20a8b1 !important;
}
#bookmarksBox.mobile .bookmarkList .bookmarkFolder.othersBookmarks ul{
@ -440,14 +507,14 @@
}
#bookmarksBox.mobile .bookmarkList > ul{
max-height:none;
width:85% !important;
/* width:85% !important;*/
}
#bookmarksBox.mobile .bookmarkList li.bookmarkFolder .folderLabel{
box-shadow:0 1px 0 #20a8b1 !important;
}
#bookmarksBox.mobile .bookmarkList ul li.bookmarkFolder ul{
width:85% !important;
margin-left:15% !important;
width:90% !important;
margin-left:10% !important;
}
#bookmarksBox.mobile .bookmarkList ul li.bookmarkFolder.othersBookmarks ul{
width:100% !important;
@ -461,7 +528,7 @@
}
#bookmarksBox.mobile .addForm,
#bookmarksBox.mobile .addForm *{
height:35px;
height:35px !important;
padding:0;
}
#bookmarksBox.mobile .addForm a{
@ -469,14 +536,14 @@
}
#bookmarksBox.mobile .addForm a{
width:25% !important;
/* width:25% !important;*/
}
#bookmarksBox.mobile .addForm input{
width:50% !important;
/* width:50% !important;*/
text-indent:10px;
}
#bookmarksBox.mobile #bkmrk_portals .addForm input{
width:75% !important;
/* width:75% !important;*/
}
#bookmarksBox.mobile #bookmarksTypeBar h5,
#bookmarksBox.mobile .bookmarkList .addForm a{
@ -530,10 +597,10 @@
#bookmarksBox.mobile .bookmarkList .bookmarkFolder.open .folderLabel > span > span{
display:block !important;
}
/**********************************************
DIALOG BOX
**********************************************/
/*---- Auto Drawer -----*/
#bkmrksAutoDrawer,
#bkmrksAutoDrawer p,

View File

@ -0,0 +1,198 @@
// ==UserScript==
// @id iitc-plugin-fix-googlemap-china-offset@breezewish
// @name IITC plugin: Fix Google Map offsets in China
// @category Tweaks
// @version 0.0.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Show correct Google Map for China user by applying offset tweaks.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.fixChinaOffset = {};
// Before understanding how this plugin works, you should know 3 points:
//
// Point1.
// The coordinate system of Ingress is WGS-84.
// However, the tiles of Google maps (except satellite map) in China have
// offsets (base on GCJ-02 coordinate system) by China policy.
// That means, if you request map tiles by giving GCJ-02 position, you
// will get the correct map.
//
// Point2.
// Currently there are no easy algorithm to transform from GCJ-02 to WGS-84,
// but we can easily transform data from WGS-84 to GCJ-02.
//
// Point3.
// When using Google maps in IITC, the layer structure looks like this:
// ----------------------
// | Other Leaflet layers | (Including portals, links, fields, and so on)
// ----------------------
// | L.Google | (Only for controling)
// ----------------------
// | Google Map layer | (Generated by Google Map APIs, for rendering maps)
// ----------------------
//
// When users are interacting with L.Google (for example, dragging, zooming),
// L.Google will perform the same action on the Google Map layer using Google
// Map APIs.
//
// So, here is the internal of the plugin:
//
// The plugin overwrites behaviours of L.Google. When users are dragging the map,
// L.Google will pass offseted positions to Google Map APIs (WGS-84 to GCJ-02).
// So Google Map APIs will render a correct map.
//
// The offset between Google maps and Ingress objects can also be fixed by applying
// WGS-84 to GCJ-02 transformation on Ingress objects. However we cannot simply know
// the requesting bounds of Ingress objects because we cannot transform GCJ-02 to
// WGS-84. As a result, the Ingress objects on maps would be incomplete.
//
// The algorithm of transforming WGS-84 to GCJ-02 comes from:
// https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936
// There is no official algorithm because it is classified information.
/////////// begin WGS84 to GCJ-02 transformer /////////
var WGS84transformer = window.plugin.fixChinaOffset.WGS84transformer = function() {};
// Krasovsky 1940
//
// a = 6378245.0, 1/f = 298.3
// b = a * (1 - f)
// ee = (a^2 - b^2) / a^2;
WGS84transformer.prototype.a = 6378245.0;
WGS84transformer.prototype.ee = 0.00669342162296594323;
WGS84transformer.prototype.transform = function(wgLat, wgLng) {
if(this.isOutOfChina(wgLat, wgLng))
return {lat: wgLat, lng: wgLng};
dLat = this.transformLat(wgLng - 105.0, wgLat - 35.0);
dLng = this.transformLng(wgLng - 105.0, wgLat - 35.0);
radLat = wgLat / 180.0 * Math.PI;
magic = Math.sin(radLat);
magic = 1 - this.ee * magic * magic;
sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtMagic) * Math.PI);
dLng = (dLng * 180.0) / (this.a / sqrtMagic * Math.cos(radLat) * Math.PI);
mgLat = wgLat + dLat;
mgLng = wgLng + dLng;
return {lat: mgLat, lng: mgLng};
};
WGS84transformer.prototype.isOutOfChina = function(lat, lng) {
if(lng < 72.004 || lng > 137.8347) return true;
if(lat < 0.8293 || lat > 55.8271) return true;
return false;
};
WGS84transformer.prototype.transformLat = function(x, y) {
var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0;
return ret;
};
WGS84transformer.prototype.transformLng = function(x, y) {
var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
return ret;
};
/////////// end WGS84 to GCJ-02 transformer /////////
var WGS84toGCJ02 = new WGS84transformer();
/////////// begin overwrited L.Google /////////
window.plugin.fixChinaOffset.L = {};
window.plugin.fixChinaOffset.L.Google = {
_update: function(e) {
if(!this._google) return;
this._resize();
var center = e && e.latlng ? e.latlng : this._map.getCenter();
///// modified here ///
var _center = window.plugin.fixChinaOffset.getLatLng(center, this._type);
///////////////////////
this._google.setCenter(_center);
this._google.setZoom(this._map.getZoom());
this._checkZoomLevels();
},
_handleZoomAnim: function (e) {
var center = e.center;
///// modified here ///
var _center = window.plugin.fixChinaOffset.getLatLng(center, this._type);
///////////////////////
this._google.setCenter(_center);
this._google.setZoom(e.zoom);
}
}
/////////// end overwrited L.Google /////////
window.plugin.fixChinaOffset.getLatLng = function(pos, type) {
// No offsets in satellite and hybrid maps
if(type !== 'SATELLITE' && type !== 'HYBRID') {
var newPos = WGS84toGCJ02.transform(pos.lat, pos.lng);
return new google.maps.LatLng(newPos.lat, newPos.lng);
} else {
return new google.maps.LatLng(pos.lat, pos.lng);
}
};
window.plugin.fixChinaOffset.overwrite = function(dest, src) {
for(var key in src) {
if(src.hasOwnProperty(key)) {
dest[key] = src[key];
}
}
}
var setup = function() {
window.plugin.fixChinaOffset.overwrite(L.Google.prototype, window.plugin.fixChinaOffset.L.Google);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -158,19 +158,17 @@ From here you can remove/disable individual plugins or IITC itself.
END
),
'mobile-plugins' => Array ( "IITC Mobile: Is it possible to add other plugins to IITC Mobile?",
'mobile-plugins' => Array ( "IITC Mobile: Is it possible to add external plugins to IITC Mobile?",
<<<'END'
Yes it is!
<ul>
<li>Create a folder named "IITC_Mobile" in your home directory.</li>
<li>Inside this folder, create a new folder named "plugins".</li>
<li>Copy all your additional plugins to this folder.</li>
<li>You should see your plugins listed above the official plugins.</li>
<li>Navigate to the IITC Plugins preference screen and click the (+) icon at the top right. You can select the script using a file explorer of your choice.</li>
<li>IITCm creates a new folder in your home directory, named "IITC_Mobile". Inside this folder you'll find a "plugins" folder where all external plugins are copied to.</li>
</ul>
Note:
<ul>
<li>The filename has to end with *.user.js.</li>
<li>If you don't know where to find your home directory: Enable dev-mode in the settings and follow the hint.</li>
<li>You need a file explorer app installed to add external plugins</li>
</ul>
END
),