user plugins back to top + use header categories

This commit is contained in:
Philipp Schaefer
2013-09-12 12:07:32 +02:00
parent 63467df342
commit aa219300f8
6 changed files with 248 additions and 30 deletions

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cradle.iitc_mobile"
android:versionCode="45"
android:versionName="0.6.1">
android:versionCode="46"
android:versionName="0.6.2">
<uses-sdk
android:minSdkVersion="14"

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:baselineAligned="false"
android:gravity="center_vertical"
android:minHeight="48dp"
android:paddingRight="?android:attr/scrollbarSize" >
<RelativeLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginBottom="6dip"
android:layout_marginLeft="6dip"
android:layout_marginRight="6dip"
android:layout_marginTop="6dip"
android:layout_weight="1" >
<TextView
android:id="@+id/plug_pref_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/plug_pref_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
</LinearLayout>

View File

@ -10,4 +10,7 @@
<dimen name="icon_margin">8dp</dimen>
<dimen name="header_icon_width">28dp</dimen>
</resources>

View File

@ -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<Header> mHeaders;
// we use a tree map to have a map with alphabetical order
private static TreeMap<String, ArrayList<IITC_PluginPreference>> 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<Header> 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<String, ArrayList<IITC_PluginPreference>>();
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 <storage-path>/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 <storage-path>/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<String, ArrayList<IITC_PluginPreference>> 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<Header> {
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<Header> 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;
}
}
}

View File

@ -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);
}
}

View File

@ -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);