From aa219300f89c18e5f2f68ff3d56f2a6dd1b1b45d Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Thu, 12 Sep 2013 12:07:32 +0200 Subject: [PATCH] user plugins back to top + use header categories --- mobile/AndroidManifest.xml | 4 +- mobile/res/layout/preference_header_item.xml | 40 ++++ mobile/res/values/dimens.xml | 3 + .../IITC_PluginPreferenceActivity.java | 226 ++++++++++++++++-- .../iitc_mobile/IITC_WebViewClient.java | 4 +- .../fragments/PluginsFragment.java | 1 + 6 files changed, 248 insertions(+), 30 deletions(-) create mode 100644 mobile/res/layout/preference_header_item.xml diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml index 6dfcfe5e..9b9bd2d7 100644 --- a/mobile/AndroidManifest.xml +++ b/mobile/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="46" + android:versionName="0.6.2"> + + + + + + + + + + + \ No newline at end of file diff --git a/mobile/res/values/dimens.xml b/mobile/res/values/dimens.xml index c67784b4..a8d390d0 100644 --- a/mobile/res/values/dimens.xml +++ b/mobile/res/values/dimens.xml @@ -10,4 +10,7 @@ 8dp + 28dp + + \ No newline at end of file diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreferenceActivity.java b/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreferenceActivity.java index db32c48e..333a0cef 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreferenceActivity.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreferenceActivity.java @@ -1,12 +1,20 @@ package com.cradle.iitc_mobile; import android.app.ActionBar; +import android.content.Context; import android.content.res.AssetManager; import android.os.Bundle; import android.os.Environment; import android.preference.PreferenceActivity; +import android.text.TextUtils; import android.util.Log; +import android.view.LayoutInflater; 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 java.io.File; import java.io.FileNotFoundException; @@ -22,6 +30,16 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { private List
mHeaders; // we use a tree map to have a map with alphabetical order private static TreeMap> sPlugins = null; + public static final String USER_PLUGIN = "00000"; + + @Override + public void setListAdapter(ListAdapter adapter) { + if (adapter == null) { + super.setListAdapter(null); + } else { + super.setListAdapter(new HeaderAdapter(this, mHeaders)); + } + } @Override public void onBuildHeaders(List
target) { @@ -35,6 +53,8 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { Log.d("iitcm", "opened plugin prefs the first time since app start -> parse plugins"); sPlugins = new TreeMap>(); setUpPluginPreferenceScreen(); + } else { + checkForNewPlugins(); } addHeaders(); } @@ -56,9 +76,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { return sPlugins.get(key); } - void setUpPluginPreferenceScreen() { - - // get all plugins from asset manager + private String[] getAssetPlugins() { AssetManager am = getAssets(); String[] asset_array = null; try { @@ -67,13 +85,44 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { // TODO Auto-generated catch block e.printStackTrace(); } + if (asset_array == null) { + asset_array = new String[0]; + } + return asset_array; + } + + private File[] getUserPlugins() { + String iitc_path = Environment.getExternalStorageDirectory().getPath() + + "/IITC_Mobile/"; + File directory = new File(iitc_path + "plugins/"); + File[] files = directory.listFiles(); + if (files == null) { + files = new File[0]; + } + return files; + } + + void checkForNewPlugins() { + File[] user = getUserPlugins(); + String[] official = getAssetPlugins(); + if ((user.length + official.length) != sPlugins.size()) { + Log.d("iitcm", "new or less plugins found since last start, rebuild preferences"); + sPlugins.clear(); + setUpPluginPreferenceScreen(); + } + } + + void setUpPluginPreferenceScreen() { + + // get all plugins from asset manager + String[] asset_array = getAssetPlugins(); for (String anAsset_array : asset_array) { // find user plugin name for user readable entries Scanner s = null; String src = ""; try { - s = new Scanner(am.open("plugins/" + anAsset_array)) + s = new Scanner(getAssets().open("plugins/" + anAsset_array)) .useDelimiter("\\A"); } catch (IOException e2) { // TODO Auto-generated catch block @@ -85,32 +134,27 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { addPluginPreference(src, anAsset_array, false); } - // load additional plugins from /IITC_Mobile/plugins/ - String iitc_path = Environment.getExternalStorageDirectory().getPath() - + "/IITC_Mobile/"; - File directory = new File(iitc_path + "plugins/"); - File[] files = directory.listFiles(); - if (files != null) { + // load user plugins from /IITC_Mobile/plugins/ + File[] files = getUserPlugins(); + for (File file : files) { Scanner s = null; String src = ""; - for (File file : files) { - try { - s = new Scanner(file).useDelimiter("\\A"); - } catch (FileNotFoundException e) { - e.printStackTrace(); - Log.d("iitcm", "failed to parse file " + file); - } - if (s != null) - src = s.hasNext() ? s.next() : ""; - - // now we have all stuff together and can build the pref screen - addPluginPreference(src, file.toString(), true); + try { + s = new Scanner(file).useDelimiter("\\A"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + Log.d("iitcm", "failed to parse file " + file); } + if (s != null) + src = s.hasNext() ? s.next() : ""; + + // now we have all stuff together and can build the pref screen + addPluginPreference(src, file.toString(), true); } } void addPluginPreference(String src, String plugin_key, - boolean additional) { + boolean user) { // now parse plugin name, description and category String header = src.substring(src.indexOf("==UserScript=="), @@ -137,9 +181,9 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { plugin_name = plugin_name.replace("IITC Plugin: ", ""); plugin_name = plugin_name.replace("IITC plugin: ", ""); - // add [User] tag to additional plugins - if (additional) - plugin_cat = "[User] " + plugin_cat; + // add [User] tag to user plugins + if (user) + plugin_cat = USER_PLUGIN + plugin_cat; // now we have all stuff together and can build the preference // first check if we need a new category @@ -160,12 +204,28 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { } void addHeaders() { + boolean first_user = true; + boolean first_official = true; // every fragment handles 1 plugin category // push the category to the fragment and add the header to the list for (Map.Entry> entry : sPlugins.entrySet()) { Bundle bundle = new Bundle(); String plugin_cat = entry.getKey(); bundle.putString("category", plugin_cat); + if (plugin_cat.startsWith(USER_PLUGIN)) { + if (first_user) { + Header category = new Header(); + category.title = "User Plugins"; + first_user = false; + mHeaders.add(category); + } + plugin_cat = plugin_cat.replace(USER_PLUGIN, ""); + } else if (first_official) { + Header category = new Header(); + category.title = "Official Plugins"; + first_official = false; + mHeaders.add(category); + } Header newHeader = new Header(); newHeader.title = plugin_cat; newHeader.fragmentArguments = bundle; @@ -173,4 +233,118 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { mHeaders.add(newHeader); } } + + /* + * This code is only for header categories. Thx to Android that we haven't this by default and + * thx to Stackoverflow for this post: http://stackoverflow.com/a/18720212 + */ + private static class HeaderAdapter extends ArrayAdapter
{ + static final int HEADER_TYPE_CATEGORY = 0; + static final int HEADER_TYPE_NORMAL = 1; + private static final int HEADER_TYPE_COUNT = HEADER_TYPE_NORMAL + 1; + + private static class HeaderViewHolder { + TextView title; + TextView summary; + } + + private LayoutInflater mInflater; + + static int getHeaderType(Header header) { + if (header.fragment == null && header.intent == null) { + return HEADER_TYPE_CATEGORY; + } else { + return HEADER_TYPE_NORMAL; + } + } + + @Override + public int getItemViewType(int position) { + Header header = getItem(position); + return getHeaderType(header); + } + + @Override + public boolean areAllItemsEnabled() { + return false; // because of categories + } + + @Override + public boolean isEnabled(int position) { + return getItemViewType(position) != HEADER_TYPE_CATEGORY; + } + + @Override + public int getViewTypeCount() { + return HEADER_TYPE_COUNT; + } + + @Override + public boolean hasStableIds() { + return true; + } + + public HeaderAdapter(Context context, List
objects) { + super(context, 0, objects); + + mInflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + HeaderViewHolder holder; + Header header = getItem(position); + int headerType = getHeaderType(header); + View view = null; + + if (convertView == null) { + holder = new HeaderViewHolder(); + switch (headerType) { + case HEADER_TYPE_CATEGORY: + view = new TextView(getContext(), null, + android.R.attr.listSeparatorTextViewStyle); + holder.title = (TextView) view; + break; + + case HEADER_TYPE_NORMAL: + view = mInflater.inflate(R.layout.preference_header_item, + parent, false); + holder.title = (TextView) view + .findViewById(R.id.plug_pref_title); + holder.summary = (TextView) view + .findViewById(R.id.plug_pref_summary); + break; + } + view.setTag(holder); + } else { + view = convertView; + holder = (HeaderViewHolder) view.getTag(); + } + + // All view fields must be updated every time, because the view may + // be recycled + switch (headerType) { + case HEADER_TYPE_CATEGORY: + holder.title.setText(header.getTitle(getContext() + .getResources())); + break; + case HEADER_TYPE_NORMAL: + holder.title.setText(header.getTitle(getContext() + .getResources())); + CharSequence summary = header.getSummary(getContext() + .getResources()); + if (!TextUtils.isEmpty(summary)) { + holder.summary.setVisibility(View.VISIBLE); + holder.summary.setText(summary); + } else { + holder.summary.setVisibility(View.GONE); + } + break; + } + + return view; + } + } } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index cc1fd222..b860ec17 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -187,9 +187,9 @@ public class IITC_WebViewClient extends WebViewClient { + plugin, false); else js += this.removePluginWrapper("plugins/" + plugin, true); - // load additional iitc plugins + // load user iitc plugins } else { - Log.d("iitcm", "adding additional plugin " + plugin); + Log.d("iitcm", "adding user plugin " + plugin); js += this.removePluginWrapper(plugin, false); } } diff --git a/mobile/src/com/cradle/iitc_mobile/fragments/PluginsFragment.java b/mobile/src/com/cradle/iitc_mobile/fragments/PluginsFragment.java index 96094054..07a7e538 100644 --- a/mobile/src/com/cradle/iitc_mobile/fragments/PluginsFragment.java +++ b/mobile/src/com/cradle/iitc_mobile/fragments/PluginsFragment.java @@ -34,6 +34,7 @@ public class PluginsFragment extends PreferenceFragment { // set action bar stuff ActionBar bar = getActivity().getActionBar(); + category = category.replace(IITC_PluginPreferenceActivity.USER_PLUGIN, "User "); bar.setTitle("IITC Plugins: " + category); bar.setDisplayHomeAsUpEnabled(true); getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);