diff --git a/code/boot.js b/code/boot.js index d9fb8ced..de78ee60 100644 --- a/code/boot.js +++ b/code/boot.js @@ -507,7 +507,8 @@ window.setupLayerChooserApi = function() { function boot() { try { //EXPERIMENTAL TEST - window.debug.console.overwriteNativeIfRequired(); + if(!isSmartphone()) // TODO remove completly? + window.debug.console.overwriteNativeIfRequired(); console.log('loading done, booting. Built: @@BUILDDATE@@'); if(window.deviceID) console.log('Your device ID: ' + window.deviceID); diff --git a/mobile/res/drawable-hdpi/ic_action_error_red.png b/mobile/res/drawable-hdpi/ic_action_error_red.png new file mode 100644 index 00000000..11b15bf5 Binary files /dev/null and b/mobile/res/drawable-hdpi/ic_action_error_red.png differ diff --git a/mobile/res/drawable-hdpi/ic_action_warning_yellow.png b/mobile/res/drawable-hdpi/ic_action_warning_yellow.png new file mode 100644 index 00000000..a17ff07b Binary files /dev/null and b/mobile/res/drawable-hdpi/ic_action_warning_yellow.png differ diff --git a/mobile/res/drawable-mdpi/ic_action_error_red.png b/mobile/res/drawable-mdpi/ic_action_error_red.png new file mode 100644 index 00000000..32c908f5 Binary files /dev/null and b/mobile/res/drawable-mdpi/ic_action_error_red.png differ diff --git a/mobile/res/drawable-mdpi/ic_action_warning_yellow.png b/mobile/res/drawable-mdpi/ic_action_warning_yellow.png new file mode 100644 index 00000000..f490edf4 Binary files /dev/null and b/mobile/res/drawable-mdpi/ic_action_warning_yellow.png differ diff --git a/mobile/res/drawable-xhdpi/ic_action_error_red.png b/mobile/res/drawable-xhdpi/ic_action_error_red.png new file mode 100644 index 00000000..f0a24cd2 Binary files /dev/null and b/mobile/res/drawable-xhdpi/ic_action_error_red.png differ diff --git a/mobile/res/drawable-xhdpi/ic_action_warning_yellow.png b/mobile/res/drawable-xhdpi/ic_action_warning_yellow.png new file mode 100644 index 00000000..2349e7e4 Binary files /dev/null and b/mobile/res/drawable-xhdpi/ic_action_warning_yellow.png differ diff --git a/mobile/res/drawable-xxhdpi/ic_action_error_red.png b/mobile/res/drawable-xxhdpi/ic_action_error_red.png new file mode 100644 index 00000000..7f13403e Binary files /dev/null and b/mobile/res/drawable-xxhdpi/ic_action_error_red.png differ diff --git a/mobile/res/drawable-xxhdpi/ic_action_warning_yellow.png b/mobile/res/drawable-xxhdpi/ic_action_warning_yellow.png new file mode 100644 index 00000000..6b729940 Binary files /dev/null and b/mobile/res/drawable-xxhdpi/ic_action_warning_yellow.png differ diff --git a/mobile/res/layout/activity_main.xml b/mobile/res/layout/activity_main.xml index d4a8ccbc..2d95b955 100644 --- a/mobile/res/layout/activity_main.xml +++ b/mobile/res/layout/activity_main.xml @@ -4,20 +4,58 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - + android:orientation="vertical"> + + + + + + + + + + + + + + diff --git a/mobile/res/layout/view_log_msg.xml b/mobile/res/layout/view_log_msg.xml new file mode 100644 index 00000000..b8ec471a --- /dev/null +++ b/mobile/res/layout/view_log_msg.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/mobile/res/menu/main.xml b/mobile/res/menu/main.xml index 63790b3f..bffdd6ab 100644 --- a/mobile/res/menu/main.xml +++ b/mobile/res/menu/main.xml @@ -1,48 +1,52 @@ - - + + + - + android:title="@string/locate"/> - + android:title="@string/layer_chooser"/> - + android:title="@string/toggle_fullscreen"/> - + android:title="@string/reload"/> - + android:title="@string/menu_clear_cookies"/> - - + android:title="@string/action_settings"/> + + + \ No newline at end of file diff --git a/mobile/res/values/strings.xml b/mobile/res/values/strings.xml index 816353f7..0c93c513 100644 --- a/mobile/res/values/strings.xml +++ b/mobile/res/values/strings.xml @@ -2,6 +2,7 @@ IITC Mobile + Toggle map visibility IITC Mobile Settings IITC Plugins Share using… @@ -140,6 +141,7 @@ Clear Cookies Search + Debug Choose account to login Login failed. Search Locations diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_LogAdapter.java b/mobile/src/com/cradle/iitc_mobile/IITC_LogAdapter.java new file mode 100644 index 00000000..2244ac16 --- /dev/null +++ b/mobile/src/com/cradle/iitc_mobile/IITC_LogAdapter.java @@ -0,0 +1,89 @@ +package com.cradle.iitc_mobile; + +import android.annotation.SuppressLint; +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import com.cradle.iitc_mobile.Log.Message; + +import java.text.SimpleDateFormat; + +public class IITC_LogAdapter extends ArrayAdapter implements Log.Receiver { + @SuppressLint("SimpleDateFormat") + private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("HH:mm:ss.SSS"); + + private int mObservers = 0; + private IITC_Mobile mIitc; + + public IITC_LogAdapter(IITC_Mobile iitc) { + super(iitc, 0); + mIitc = iitc; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + Message item = getItem(position); + View v = mIitc.getLayoutInflater().inflate(R.layout.view_log_msg, parent, false); + + ImageView iv = (ImageView) v.findViewById(R.id.log_type); + switch (item.getPriority()) { + case Log.ASSERT: + case Log.ERROR: + iv.setImageResource(R.drawable.ic_action_error_red); + break; + case Log.WARN: + iv.setImageResource(R.drawable.ic_action_warning_yellow); + break; + default: + iv.setImageResource(R.drawable.ic_action_about); + } + + TextView tv; + + tv = (TextView) v.findViewById(R.id.log_tag); + tv.setText(item.getTag()); + + tv = (TextView) v.findViewById(R.id.log_time); + tv.setText(FORMATTER.format(item.getDate())); + + tv = (TextView) v.findViewById(R.id.log_msg); + tv.setText(item.getMsg()); + + return v; + } + + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + super.unregisterDataSetObserver(observer); + mObservers--; + + if (mObservers < 1) { + clear(); + Log.removeReceiver(this); + } + } + + @Override + public void registerDataSetObserver(DataSetObserver observer) { + super.registerDataSetObserver(observer); + + if (mObservers < 1) + Log.addReceiver(this); + + mObservers++; + } + + @Override + public void handle(Message message) { + this.insert(message, 0); + } +} diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java index 4080e985..b729c581 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java @@ -24,6 +24,9 @@ import android.view.View; import android.view.Window; import android.webkit.CookieManager; import android.webkit.WebView; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.ListView; import android.widget.SearchView; import android.widget.Toast; @@ -49,8 +52,15 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis private boolean mDesktopMode = false; private boolean mAdvancedMenu = false; private MenuItem mSearchMenuItem; + private View mImageLoading; + private ListView mLvDebug; + private View mViewDebug; + private ImageButton mBtnToggleMap; + private EditText mEditCommand; + private boolean mDebugging = false; private boolean mReloadNeeded = false; private boolean mIsLoading = true; + private boolean mShowMapInDebug = false; private final Stack mDialogStack = new Stack(); // Used for custom back stack handling @@ -73,7 +83,14 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis requestWindowFeature(Window.FEATURE_PROGRESS); setContentView(R.layout.activity_main); + mImageLoading = findViewById(R.id.imageLoading); mIitcWebView = (IITC_WebView) findViewById(R.id.iitc_webview); + mLvDebug = (ListView) findViewById(R.id.lvDebug); + mViewDebug = findViewById(R.id.viewDebug); + mBtnToggleMap = (ImageButton) findViewById(R.id.btnToggleMapVisibility); + mEditCommand = (EditText) findViewById(R.id.editCommand); + + mLvDebug.setAdapter(new IITC_LogAdapter(this)); // do something if user changed something in the settings mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); @@ -425,6 +442,11 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis : R.drawable.ic_action_location_found); break; + case R.id.menu_debug: + item.setVisible(mAdvancedMenu && visible); + item.setChecked(mDebugging); + break; + default: item.setVisible(visible); } @@ -480,6 +502,13 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis CookieManager cm = CookieManager.getInstance(); cm.removeAllCookie(); return true; + case R.id.menu_debug: + mDebugging = !mDebugging; + updateViews(); + invalidateOptionsMenu(); + + // TODO remove debugging stuff from JS? + return true; default: return false; } @@ -494,6 +523,7 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis mNavigationHelper.reset(); mMapSettings.reset(); mUserLocation.reset(); + mIitcWebView.getWebViewClient().reset(); mBackStack.clear(); // iitc starts on map after reload mCurrentPane = Pane.MAP; @@ -585,15 +615,54 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis mNavigationHelper.onLoadingStateChanged(); - if (isLoading && !mSharedPrefs.getBoolean("pref_disable_splash", false)) { - findViewById(R.id.iitc_webview).setVisibility(View.GONE); - findViewById(R.id.imageLoading).setVisibility(View.VISIBLE); + updateViews(); + } + + private void updateViews() { + if (!mDebugging) { + mViewDebug.setVisibility(View.GONE); + mLvDebug.setVisibility(View.GONE); + + if (mIsLoading && !mSharedPrefs.getBoolean("pref_disable_splash", false)) { + mIitcWebView.setVisibility(View.GONE); + mImageLoading.setVisibility(View.VISIBLE); + } else { + mIitcWebView.setVisibility(View.VISIBLE); + mImageLoading.setVisibility(View.GONE); + } } else { - findViewById(R.id.iitc_webview).setVisibility(View.VISIBLE); - findViewById(R.id.imageLoading).setVisibility(View.GONE); + // if the debug container is invisible (and we are about to show it), select the text box + boolean select = mViewDebug.getVisibility() != View.VISIBLE; + + mImageLoading.setVisibility(View.GONE); // never show splash screen while debugging + mViewDebug.setVisibility(View.VISIBLE); + + if (select) { + mEditCommand.requestFocus(); + mEditCommand.selectAll(); + } + + if (mShowMapInDebug) { + mBtnToggleMap.setImageResource(R.drawable.ic_action_view_as_list); + mIitcWebView.setVisibility(View.VISIBLE); + mLvDebug.setVisibility(View.GONE); + } else { + mBtnToggleMap.setImageResource(R.drawable.ic_action_map); + mIitcWebView.setVisibility(View.GONE); + mLvDebug.setVisibility(View.VISIBLE); + } } } + /** + * onClick handler for R.id.btnToggleMapVisibility, assigned in activity_main.xml + */ + public void onToggleMapVisibility(View v) + { + mShowMapInDebug = !mShowMapInDebug; + updateViews(); + } + private void deleteUpdateFile() { File file = new File(getExternalFilesDir(null).toString() + "/iitcUpdate.apk"); if (file != null) file.delete(); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java b/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java index 9c4df290..5b68fb33 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java @@ -336,16 +336,11 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt add(Pane.COMPACT); add(Pane.PUBLIC); add(Pane.FACTION); - - if (mPrefs.getBoolean("pref_advanced_menu", false)) { - add(Pane.DEBUG); - } } } public static class Pane { public static final Pane COMPACT = new Pane("compact", "Compact", R.drawable.ic_action_view_as_list_compact); - public static final Pane DEBUG = new Pane("debug", "Debug", R.drawable.ic_action_error); public static final Pane FACTION = new Pane("faction", "Faction", R.drawable.ic_action_cc_bcc); public static final Pane FULL = new Pane("full", "Full", R.drawable.ic_action_view_as_list); public static final Pane INFO = new Pane("info", "Info", R.drawable.ic_action_about); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java index a191f9ef..fad0eee3 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java @@ -15,14 +15,14 @@ public class IITC_WebChromeClient extends WebChromeClient { public IITC_WebChromeClient(IITC_Mobile iitcm) { mIitcm = iitcm; } + /** * our webchromeclient should share geolocation with the iitc script * * allow access by default */ @Override - public void onGeolocationPermissionsShowPrompt(String origin, - GeolocationPermissions.Callback callback) { + public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { callback.invoke(origin, true, false); } @@ -42,10 +42,14 @@ public class IITC_WebChromeClient extends WebChromeClient { * remove splash screen if any JS error occurs */ @Override - public boolean onConsoleMessage(ConsoleMessage consoleMessage) { - if (consoleMessage.messageLevel() == ConsoleMessage.MessageLevel.ERROR) { + public boolean onConsoleMessage(ConsoleMessage message) { + if (message.messageLevel() == ConsoleMessage.MessageLevel.ERROR) { mIitcm.setLoadingState(false); } - return super.onConsoleMessage(consoleMessage); + + if (Log.log(message)) + return true; // message was handled + + return super.onConsoleMessage(message); } } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index e0934d8f..c2337785 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -6,6 +6,7 @@ import android.net.Uri; import android.net.http.SslError; import android.os.Environment; import android.preference.PreferenceManager; +import android.text.TextUtils; import android.util.Log; import android.webkit.SslErrorHandler; import android.webkit.WebResourceResponse; @@ -86,7 +87,7 @@ public class IITC_WebViewClient extends WebViewClient { scripts.add("script/user-location.user.js"); } - String js = "(function(){['" + join(scripts, "','") + "'].forEach(function(src) {" + + String js = "(function(){['" + TextUtils.join("','", scripts) + "'].forEach(function(src) {" + "var script = document.createElement('script');script.src = 'iitcm://'+src;" + "(document.body || document.head || document.documentElement).appendChild(script);" + "});})();"; @@ -94,64 +95,16 @@ public class IITC_WebViewClient extends WebViewClient { view.loadJS(js); } - static public String join(List list, String conjunction) - { - StringBuilder sb = new StringBuilder(); - boolean first = true; - for (String item : list) - { - if (first) - first = false; - else - sb.append(conjunction); - sb.append(item); - } - return sb.toString(); - } - /** * this method is called automatically when the Google login form is opened. */ @Override public void onReceivedLoginRequest(WebView view, String realm, String account, String args) { - Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args); mIitcInjected = false; + // Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args); // ((IITC_Mobile) mContext).onReceivedLoginRequest(this, view, realm, account, args); } - // read a file into a string - // use the full path for File - // if asset == true use the asset manager to open file - // public String fileToString(String file, boolean asset) { - // Scanner s = null; - // String src = ""; - // if (!asset) { - // File js_file = new File(file); - // try { - // s = new Scanner(js_file).useDelimiter("\\A"); - // } catch (FileNotFoundException e) { - // e.printStackTrace(); - // Log.d("iitcm", "failed to parse file " + file); - // return "false"; - // } - // } else { - // // load plugins from asset folder - // AssetManager am = mIitc.getAssets(); - // try { - // s = new Scanner(am.open(file)).useDelimiter("\\A"); - // } catch (IOException e) { - // e.printStackTrace(); - // Log.d("iitcm", "failed to parse file assets/" + file); - // return "false"; - // } - // } - // - // if (s != null) { - // src = s.hasNext() ? s.next() : ""; - // } - // return src; - // } - // Check every external resource if it’s okay to load it and maybe replace // it // with our own content. This is used to block loading Niantic resources @@ -220,4 +173,8 @@ public class IITC_WebViewClient extends WebViewClient { return true; } } + + public void reset() { + mIitcInjected = false; + } } diff --git a/mobile/src/com/cradle/iitc_mobile/Log.java b/mobile/src/com/cradle/iitc_mobile/Log.java new file mode 100644 index 00000000..e0ca4e1e --- /dev/null +++ b/mobile/src/com/cradle/iitc_mobile/Log.java @@ -0,0 +1,220 @@ +package com.cradle.iitc_mobile; + +import android.webkit.ConsoleMessage; +import android.webkit.ConsoleMessage.MessageLevel; + +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +public final class Log { + private static final HashMap CONSOLE_MAPPING; + private static final List RECEIVERS = new LinkedList(); + + public static final String CONSOLE_TAG = "iitcm-console"; + public static final String DEFAULT_TAG = "iitcm"; + + public static final int ASSERT = android.util.Log.ASSERT; + public static final int DEBUG = android.util.Log.DEBUG; + public static final int ERROR = android.util.Log.ERROR; + public static final int INFO = android.util.Log.INFO; + public static final int VERBOSE = android.util.Log.VERBOSE; + public static final int WARN = android.util.Log.WARN; + + static { + CONSOLE_MAPPING = new HashMap(); + CONSOLE_MAPPING.put(MessageLevel.TIP, android.util.Log.VERBOSE); + CONSOLE_MAPPING.put(MessageLevel.LOG, android.util.Log.INFO); + CONSOLE_MAPPING.put(MessageLevel.WARNING, android.util.Log.WARN); + CONSOLE_MAPPING.put(MessageLevel.ERROR, android.util.Log.ERROR); + CONSOLE_MAPPING.put(MessageLevel.DEBUG, android.util.Log.DEBUG); + }; + + private static synchronized void log(int priority, String tag, String msg, Throwable tr) { + Date now = new Date(); + + Message message = new Message(now, priority, tag, msg, tr); + for (Receiver receiver : RECEIVERS) { + receiver.handle(message); + } + } + + public static void d(String msg) { + d(DEFAULT_TAG, msg); + } + + @Deprecated + public static void d(String tag, String msg) { + log(android.util.Log.DEBUG, tag, msg, null); + android.util.Log.d(tag, msg); + } + + @Deprecated + public static void d(String tag, String msg, Throwable tr) { + log(android.util.Log.DEBUG, tag, msg, tr); + android.util.Log.d(tag, msg, tr); + } + + public static void d(String msg, Throwable tr) { + d(DEFAULT_TAG, msg, tr); + } + + public static void e(String msg) { + e(DEFAULT_TAG, msg); + } + + @Deprecated + public static void e(String tag, String msg) { + log(android.util.Log.ERROR, tag, msg, null); + android.util.Log.e(tag, msg); + } + + @Deprecated + public static void e(String tag, String msg, Throwable tr) { + log(android.util.Log.ERROR, tag, msg, tr); + android.util.Log.e(tag, msg, tr); + } + + public static void e(String msg, Throwable tr) { + e(DEFAULT_TAG, msg, tr); + } + + public static void i(String msg) { + i(DEFAULT_TAG, msg); + } + + @Deprecated + public static void i(String tag, String msg) { + log(android.util.Log.INFO, tag, msg, null); + android.util.Log.i(tag, msg); + } + + @Deprecated + public static void i(String tag, String msg, Throwable tr) { + log(android.util.Log.INFO, tag, msg, tr); + android.util.Log.i(tag, msg, tr); + } + + public static void i(String msg, Throwable tr) { + i(DEFAULT_TAG, msg, tr); + } + + public static boolean log(ConsoleMessage message) { + final String msg = message.sourceId() + ":" + message.lineNumber() + ": " + message.message(); + final Integer priority = CONSOLE_MAPPING.get(message.messageLevel()); + + if (priority != null) { + log(priority, CONSOLE_TAG, msg, null); + android.util.Log.println(priority, CONSOLE_TAG, msg); + return true; + } + + Log.w(CONSOLE_TAG, "Warning: unknown message level in Logger.log(ConsoleMessage message): " + + message.messageLevel().ordinal() + "/" + message.messageLevel().name()); + return false; + } + + public static int println(int priority, String msg) { + return println(priority, DEFAULT_TAG, msg); + } + + @Deprecated + public static int println(int priority, String tag, String msg) { + log(priority, tag, msg, null); + return android.util.Log.println(priority, tag, msg); + } + + public static void v(String msg) { + v(DEFAULT_TAG, msg); + } + + @Deprecated + public static void v(String tag, String msg) { + log(android.util.Log.VERBOSE, tag, msg, null); + android.util.Log.v(tag, msg); + } + + @Deprecated + public static void v(String tag, String msg, Throwable tr) { + log(android.util.Log.VERBOSE, tag, msg, tr); + android.util.Log.v(tag, msg, tr); + } + + public static void v(String msg, Throwable tr) { + v(DEFAULT_TAG, msg, tr); + } + + public static void w(String msg) { + w(DEFAULT_TAG, msg); + } + + @Deprecated + public static void w(String tag, String msg) { + log(android.util.Log.WARN, tag, msg, null); + android.util.Log.w(tag, msg); + } + + @Deprecated + public static void w(String tag, String msg, Throwable tr) { + log(android.util.Log.WARN, tag, msg, tr); + android.util.Log.w(tag, msg, tr); + } + + public static void w(String msg, Throwable tr) { + w(DEFAULT_TAG, msg, tr); + } + + private Log() { + // prevent instantiation + throw new UnsupportedOperationException(); + } + + public static class Message { + private Date mDate; + private String mMsg; + private int mPriority; + private String mTag; + private Throwable mTr; + + private Message(Date date, int priority, String tag, String msg, Throwable tr) { + mDate = date; + mPriority = priority; + mTag = tag; + mMsg = msg; + mTr = tr; + } + + public Date getDate() { + return this.mDate; + } + + public String getMsg() { + return this.mMsg; + } + + public int getPriority() { + return this.mPriority; + } + + public String getTag() { + return this.mTag; + } + + public Throwable getTr() { + return this.mTr; + } + } + + public static interface Receiver { + void handle(Message message); + } + + public static void removeReceiver(Log.Receiver receiver) { + RECEIVERS.remove(receiver); + } + + public static void addReceiver(Log.Receiver receiver) { + RECEIVERS.add(receiver); + } +}