package net.pocketmine.forum; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Locale; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.widget.SearchView; import com.actionbarsherlock.widget.SearchView.OnQueryTextListener; import com.astuetz.PagerSlidingTabStrip; import net.pocketmine.forum.DynamicLayout.ShowViewListener; import net.pocketmine.forum.GridAdapter.DownloadImageTask; import net.pocketmine.forum.PluginListManager.PluginDownloadInfo; import net.pocketmine.server.R; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public class PluginsActivity extends SherlockFragmentActivity { public static class Plugin { public int id; public String name; public String author; public long downloadCount; public double rated; public int ratedTimes; public double ratedWeighted; public int lastUpdate; public int tag; public int category; public boolean featured; public Bitmap image; } public static class PluginMatch { public int index; public Plugin plugin; public int score; } // accent public static int color = Color.argb(255, 0, 120, 170); PagerSlidingTabStrip tabs; ViewPager pager; PluginsTabs adapter; public static ArrayList<Plugin> plugins; public static ArrayList<Plugin> pluginUpdates; public static ArrayList<Plugin> featuredPlugins; public static ArrayList<Plugin> essentialPlugins; public static ArrayList<Plugin> bestRated; public static ArrayList<Plugin> topPlugins; public static ArrayList<Plugin> topNewPlugins; public static ArrayList<Plugin> recentlyUpdated; public static PluginsActivity activity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_plugins); activity = this; ActionBar bar = getSupportActionBar(); Drawable colorDrawable = new ColorDrawable(color); Drawable bottomDrawable = getResources().getDrawable( R.drawable.actionbar_bottom); LayerDrawable ld = new LayerDrawable(new Drawable[] { colorDrawable, bottomDrawable }); bar.setBackgroundDrawable(ld); tabs = (PagerSlidingTabStrip) findViewById(R.id.plugins_tabs); pager = (ViewPager) findViewById(R.id.plugins_pager); adapter = new PluginsTabs(getSupportFragmentManager()); pager.setAdapter(adapter); tabs.setViewPager(pager); tabs.setIndicatorColor(color); pager.setCurrentItem(1); pager.setOffscreenPageLimit(10); tabs.setVisibility(View.GONE); pager.setVisibility(View.GONE); Button errorRetry = (Button) findViewById(R.id.plugins_error_retry); errorRetry.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { ProgressBar progress = (ProgressBar) findViewById(R.id.plugins_loading); LinearLayout layout = (LinearLayout) findViewById(R.id.plugins_error); progress.setVisibility(View.VISIBLE); layout.setVisibility(View.GONE); refresh(); } }); refresh(); } @Override protected void onSaveInstanceState(Bundle outState) { // super.onSaveInstanceState(outState); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { // super.onRestoreInstanceState(savedInstanceState); } @Override protected void onDestroy() { super.onDestroy(); adapter = null; } private void refresh() { new Thread(new Runnable() { @Override public void run() { StringBuilder sb = new StringBuilder(); ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = connectivityManager .getActiveNetworkInfo(); Boolean hasNetwork = activeNetworkInfo != null && activeNetworkInfo.isConnected(); if (!hasNetwork) { Log.d("Plugins", "No internet connection"); showError(R.string.plugins_error_nointernet); return; } try { URL url = new URL( "http://forums.pocketmine.net/api.php?action=getResources"); BufferedReader in = new BufferedReader( new InputStreamReader(url.openStream())); String str; while ((str = in.readLine()) != null) { sb.append(str); } in.close(); JSONObject jobj = (JSONObject) JSONValue.parse(sb .toString()); JSONArray arr = (JSONArray) jobj.get("resources"); Log.d("Plugins", "Count: " + arr.size()); plugins = new ArrayList<Plugin>(); pluginUpdates = new ArrayList<Plugin>(); featuredPlugins = new ArrayList<Plugin>(); essentialPlugins = new ArrayList<Plugin>(); bestRated = new ArrayList<Plugin>(); topPlugins = new ArrayList<Plugin>(); topNewPlugins = new ArrayList<Plugin>(); recentlyUpdated = new ArrayList<Plugin>(); for (int i = 0; i < arr.size(); i++) { JSONObject jp = (JSONObject) arr.get(i); Plugin p = new Plugin(); p.id = ((Long) jp.get("id")).intValue(); p.name = (String) jp.get("title"); p.author = (String) jp.get("author_username"); p.downloadCount = (Long) jp.get("times_downloaded"); p.rated = getDouble(jp.get("rating_avg")); p.ratedTimes = ((Long) jp.get("times_rated")) .intValue(); p.ratedWeighted = getDouble(jp.get("rating_weighted")); p.lastUpdate = ((Long) jp.get("last_update")) .intValue(); p.tag = ((Long) jp.get("prefix_id")).intValue(); p.category = ((Long) jp.get("category_id")).intValue(); p.featured = false; plugins.add(p); bestRated.add(p); topPlugins.add(p); Log.d("Plugins", "Plugin " + p.name + " found!"); if ((System.currentTimeMillis() / 1000) - p.lastUpdate < 604800) { recentlyUpdated.add(p); } long created = (Long) jp.get("creation_date"); if ((System.currentTimeMillis() / 1000) - created < 604800) { topNewPlugins.add(p); } if (jp.get("feature_date") != null) { p.featured = true; featuredPlugins.add(p); } if (p.tag == 3) { essentialPlugins.add(p); } PluginDownloadInfo info = PluginListManager .getPluginInfo(p.id); if (info != null) { if (p.lastUpdate > info.updated) { // UPDATE!!! UPDATE!!! UPDATE!!! pluginUpdates.add(p); } } } Collections.sort(bestRated, new Comparator<Plugin>() { @Override public int compare(Plugin lhs, Plugin rhs) { if (lhs.ratedWeighted > rhs.ratedWeighted) { return -1; } else if (lhs.ratedWeighted < rhs.ratedWeighted) { return 1; } else { return 0; } } }); Collections.sort(topPlugins, new Comparator<Plugin>() { @Override public int compare(Plugin lhs, Plugin rhs) { if (lhs.downloadCount > rhs.downloadCount) { return -1; } else if (lhs.downloadCount < rhs.downloadCount) { return 1; } else { return 0; } } }); Collections.sort(topNewPlugins, new Comparator<Plugin>() { @Override public int compare(Plugin lhs, Plugin rhs) { if (lhs.downloadCount > rhs.downloadCount) { return -1; } else if (lhs.downloadCount < rhs.downloadCount) { return 1; } else { return 0; } } }); Collections.sort(recentlyUpdated, new Comparator<Plugin>() { @Override public int compare(Plugin lhs, Plugin rhs) { if (lhs.lastUpdate > rhs.lastUpdate) { return -1; } else if (lhs.lastUpdate < rhs.lastUpdate) { return 1; } else { return 0; } } }); runOnUiThread(new Runnable() { @Override public void run() { tabs.setVisibility(View.VISIBLE); pager.setVisibility(View.VISIBLE); ProgressBar progress = (ProgressBar) findViewById(R.id.plugins_loading); progress.setVisibility(View.GONE); } }); } catch (Exception e) { e.printStackTrace(); showError(R.string.plugins_error_general); } } }).start(); } public Double getDouble(Object o) { if (o instanceof Double) { return (Double) o; } else if (o instanceof Long) { return ((Long) o).doubleValue(); } else if (o instanceof Integer) { return ((Integer) o).doubleValue(); } else { return null; } } public void showError(final int resId) { runOnUiThread(new Runnable() { @Override public void run() { ProgressBar progress = (ProgressBar) findViewById(R.id.plugins_loading); LinearLayout layout = (LinearLayout) findViewById(R.id.plugins_error); TextView desc = (TextView) findViewById(R.id.plugins_error_desc); progress.setVisibility(View.GONE); tabs.setVisibility(View.GONE); pager.setVisibility(View.GONE); layout.setVisibility(View.VISIBLE); desc.setText(resId); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getSupportMenuInflater().inflate(R.menu.plugins, menu); addSearch(this, getSupportActionBar(), menu); return true; } public void openSettings(MenuItem mi) { startActivity(new Intent(this, PluginsSettingsActivity.class)); } public static void addSearch(final Activity activity, ActionBar actionBar, Menu menu) { SearchView searchView = new SearchView(actionBar.getThemedContext()); searchView.setQueryHint("Search for plugins"); AutoCompleteTextView searchText = (AutoCompleteTextView) searchView .findViewById(R.id.abs__search_src_text); searchText.setHintTextColor(Color.WHITE); searchView.setOnQueryTextListener(new OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { Log.d("Search", query); if (query.length() < 3) { Toast.makeText(activity, "Enter at least 3 characters.", Toast.LENGTH_SHORT).show(); return false; } if (plugins == null) { return false; } String[] keywords = query.split(" "); int minScore = 0; for (String keyword : keywords) { minScore += keyword.length() * 2; } if (minScore - 5 > 0) { minScore -= 5; } ArrayList<PluginMatch> matches = new ArrayList<PluginsActivity.PluginMatch>(); for (int index = 0; index < plugins.size(); index++) { Plugin p = plugins.get(index); int score = 0; for (String keyword : keywords) { String keyword_replaced = keyword.replace("£", "E") .replace("$", "S").replace("¢", "C") .replace("¥", "Y").replace("€", "E") .replace("-", "").toLowerCase(Locale.US); String name = p.name.replace("£", "E") .replace("$", "S").replace("¢", "C") .replace("¥", "Y").replace("€", "E") .replace("-", "").toLowerCase(Locale.US); int iof = keyword_replaced.indexOf(Character .toString(name.charAt(0))); if (iof == -1) { break; } for (int i = 0; i < keyword_replaced.length() - iof; i++) { // some plugins overuse them char c = keyword_replaced.charAt(iof + i); if (i >= name.length()) break; char c2 = name.charAt(i); if (c == c2) { score += 2; } else if (i < keyword_replaced.length() - 1 && i < name.length() - 1) { c2 = name.charAt(i + 1); if (c == c2) { score += 1; i += 1; } else if (i < keyword_replaced.length() - 2 && i < name.length() - 2) { c2 = name.charAt(i + 2); if (c == c2) { i += 2; } } } else if (i < keyword_replaced.length() - 2 && iof + i < name.length() - 2) { c2 = name.charAt(iof + i + 2); if (c == c2) { i += 2; } } } } if (score > minScore) { PluginMatch match = new PluginMatch(); match.index = index; match.plugin = p; match.score = score; matches.add(match); } } Collections.sort(matches, new Comparator<PluginMatch>() { @Override public int compare(PluginMatch lhs, PluginMatch rhs) { if (lhs.score > rhs.score) { return -1; } else if (lhs.score < rhs.score) { return 1; } else { return 0; } } }); if (matches.size() <= 0) { Toast.makeText(activity, "No matches found.", Toast.LENGTH_SHORT).show(); return false; } int[] array = new int[matches.size()]; for (int i = 0; i < matches.size(); i++) { PluginMatch match = matches.get(i); Log.d("Match", "Found: " + match.plugin.name + " with score: " + match.score); array[i] = match.index; } Intent i = new Intent(activity, SearchResultsActivity.class); i.putExtra("query", query); i.putExtra("plugins", array); activity.startActivity(i); return true; } @Override public boolean onQueryTextChange(String newText) { return false; } }); menu.add("Search") .setIcon(R.drawable.ic_search) .setActionView(searchView) .setShowAsAction( MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); } public class PluginsTabs extends FragmentPagerAdapter { public String[] tabs = { "Categories", "Home", "Updates", "Featured", "Essential", "Best Plugins", "Top Plugins", "Top New Plugins", "Recently updated" }; public PluginsTabs(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { if (position == 0) { return new CategoriesFragment(); } else if (position == 1) { return new HomeFragment(); } else if (position == 2) { return createFragment(6); } else if (position == 3) { return createFragment(0); } else if (position == 4) { return createFragment(1); } else if (position == 5) { return createFragment(2); } else if (position == 6) { return createFragment(3); } else if (position == 7) { return createFragment(4); } else if (position == 8) { return createFragment(5); } return new ListFragment(); } private ListFragment createFragment(int id) { ListFragment fragment = new ListFragment(); Bundle args = new Bundle(); args.putInt("tab", id); fragment.setArguments(args); return fragment; } @Override public CharSequence getPageTitle(int position) { return tabs[position]; } @Override public int getCount() { return tabs.length; } } public static class TestFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return new LinearLayout(getActivity()); } } public static class HomeFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.activity_plugins_home, container, false); fillLayout(inflater, (DynamicLayout) v.findViewById(R.id.plugins_featured), featuredPlugins); fillLayout(inflater, (DynamicLayout) v.findViewById(R.id.plugins_essential), essentialPlugins); fillLayout(inflater, (DynamicLayout) v.findViewById(R.id.plugins_popular), topPlugins); Button moreFeatured = (Button) v.findViewById(R.id.more_featured); moreFeatured.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (activity != null) { activity.pager.setCurrentItem(3); } } }); Button moreEssential = (Button) v.findViewById(R.id.more_essential); moreEssential.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (activity != null) { activity.pager.setCurrentItem(4); } } }); Button morePopular = (Button) v.findViewById(R.id.more_popular); morePopular.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (activity != null) { activity.pager.setCurrentItem(6); } } }); return v; } private void fillLayout(LayoutInflater inflater, final DynamicLayout layout, final ArrayList<Plugin> plugins) { ArrayList<View> views = new ArrayList<View>(); if (plugins != null) { for (int i = 0; i < plugins.size(); i++) { Plugin plugin = plugins.get(i); if (plugin != null) { View view = GridAdapter.createCard(inflater, layout, R.layout.plugin_card2); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f); view.setLayoutParams(params); GridAdapter .fillData(getActivity(), view, plugin, false); views.add(view); } } } layout.setViews(views); layout.setOnShowViewListener(new ShowViewListener() { @Override public void show(int pos, View view) { Log.d("PluginsActivity/DownloadImageTask", "Downloading at " + pos); ImageView image = (ImageView) view .findViewById(R.id.plugin_icon); view.setTag(new DownloadImageTask(image).execute(plugins .get(pos))); } @Override public void hide(int pos) { View view = layout.getChildAt(pos); if (view != null && view.getTag() != null && view.getTag() instanceof DownloadImageTask) { DownloadImageTask task = (DownloadImageTask) view .getTag(); task.cancel = true; // there's no problem, with // finishing it to // download; just do not change // correct // image } } @Override public void clearAll() { for (int i = 0; i < layout.getChildCount(); i++) { hide(i); } } }); } } public static class CategoriesFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ListView lv = new ListView(getActivity()); final ArrayAdapter<String> adapter = new ArrayAdapter<String>( getActivity(), R.layout.plugins_category, new String[] { "Admin Tools", "Anti-Griefing Tools", "Chat Related", "Developer Tools", "Economy", "Fun", "General", "Informational", "Mechanics", "Miscellaneous", "Teleportation", "World Editing and Management", "World Generators" }); lv.setAdapter(adapter); lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> view, View view2, int pos, long id) { Intent i = new Intent(getActivity(), CategoryActivity.class); i.putExtra("category", pos + 3); i.putExtra("title", adapter.getItem(pos)); getActivity().startActivity(i); } }); return lv; } } public static class ListFragment extends Fragment { public ListFragment() { setRetainInstance(false); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { int id = getArguments().getInt("tab", 0); ArrayList<Plugin> plugins = null; if (id == 0) { plugins = featuredPlugins; } else if (id == 1) { plugins = essentialPlugins; } else if (id == 2) { plugins = bestRated; } else if (id == 3) { plugins = topPlugins; } else if (id == 4) { plugins = topNewPlugins; } else if (id == 5) { plugins = recentlyUpdated; } else if (id == 6) { plugins = pluginUpdates; } if (plugins == null) { return new LinearLayout(getActivity()); // whatever } View v = inflater.inflate(R.layout.activity_plugins_list, container, false); GridView grid = (GridView) v.findViewById(R.id.plugins_list); grid.setSelector(new ColorDrawable(Color.TRANSPARENT)); grid.setAdapter(new GridAdapter(getActivity(), plugins)); return v; } } }