diff --git a/src/org/fdroid/fdroid/AppListManager.java b/src/org/fdroid/fdroid/AppListManager.java new file mode 100644 index 000000000..59f66f161 --- /dev/null +++ b/src/org/fdroid/fdroid/AppListManager.java @@ -0,0 +1,234 @@ +package org.fdroid.fdroid; + +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.Log; +import android.widget.ArrayAdapter; + +import java.util.*; + +/** + * Should be owned by the FDroid Activity, but used by the AppListFragments. + * The idea is that it takes a non-trivial amount of time to work this stuff + * out, and it is quicker if we only do it once for each view, rather than + * each fragment figuring out their own list independently. + */ +public class AppListManager { + + private Vector allApps = null; + + private FDroid fdroidActivity; + + private AppListAdapter availableApps; + private AppListAdapter installedApps; + private AppListAdapter canUpgradeApps; + private ArrayAdapter categories; + + private String currentCategory = null; + private String categoryAll = null; + private String categoryWhatsNew = null; + private String categoryRecentlyUpdated = null; + + public AppListAdapter getAvailableAdapter() { + return availableApps; + } + + public AppListAdapter getInstalledAdapter() { + return installedApps; + } + + public AppListAdapter getCanUpdateAdapter() { + return canUpgradeApps; + } + + public ArrayAdapter getCategoriesAdapter() { + return categories; + } + + public AppListManager(FDroid activity) { + this.fdroidActivity = activity; + + availableApps = new AppListAdapter(fdroidActivity); + installedApps = new AppListAdapter(fdroidActivity); + canUpgradeApps = new AppListAdapter(fdroidActivity); + + // Needs to be created before createViews(), because that will use the + // getCategoriesAdapter() accessor which expects this object... + categories = new ArrayAdapter(activity, + android.R.layout.simple_spinner_item, new Vector()); + categories + .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + } + + private void clear() { + installedApps.clear(); + availableApps.clear(); + canUpgradeApps.clear(); + categories.clear(); + } + + private void notifyLists() { + // Tell the lists that the data behind the adapter has changed, so + // they can refresh... + availableApps.notifyDataSetChanged(); + installedApps.notifyDataSetChanged(); + canUpgradeApps.notifyDataSetChanged(); + categories.notifyDataSetChanged(); + } + + private void updateCategories() { + try { + DB db = DB.getDB(); + + // Populate the category list with the real categories, and the + // locally generated meta-categories for "All", "What's New" and + // "Recently Updated"... + categoryAll = fdroidActivity.getString(R.string.category_all); + categoryWhatsNew = fdroidActivity.getString(R.string.category_whatsnew); + categoryRecentlyUpdated = fdroidActivity.getString(R.string.category_recentlyupdated); + + categories.add(categoryWhatsNew); + categories.add(categoryRecentlyUpdated); + categories.add(categoryAll); + + for (String s : db.getCategories()) { + categories.add(s); + } + + if (currentCategory == null) + currentCategory = categoryWhatsNew; + + } finally { + DB.releaseDB(); + } + } + + // Tell the FDroid activity to update its "Update (x)" tab to correctly + // reflect the number of updates available. + private void notifyActivity() { + fdroidActivity.refreshUpdateTabLabel(); + } + + public void repopulateLists() { + + long startTime = System.currentTimeMillis(); + + clear(); + + updateCategories(); + updateApps(); + notifyLists(); + notifyActivity(); + + Log.d("FDroid", "Updated lists - " + allApps.size() + " allApps in total" + + " (update took " + (System.currentTimeMillis() - startTime) + + " ms)"); + } + + // Calculate the cutoff date we'll use for What's New and Recently + // Updated... + private Date calcMaxHistory() { + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(fdroidActivity.getBaseContext()); + String daysPreference = prefs.getString("updateHistoryDays", "14"); + int maxHistoryDays = Integer.parseInt(daysPreference); + Calendar recent = Calendar.getInstance(); + recent.add(Calendar.DAY_OF_YEAR, -maxHistoryDays); + return recent.getTime(); + } + + // recentDate could really be calculated here, but this is just a hack so + // it doesn't need to be caluculated for every single app. The reason it + // isn't an instance variable is because the preferences may change, and + // we wouldn't know. + private boolean isInCategory(DB.App app, String category, Date recentDate) { + boolean isInCategory; + if (category.equals(categoryAll)) { + isInCategory = true; + } else if (category.equals(categoryWhatsNew)) { + if (app.added == null) + isInCategory = false; + else if (app.added.compareTo(recentDate) < 0) + isInCategory = false; + else + isInCategory = true; + } else if (category.equals(categoryRecentlyUpdated)) { + if (app.lastUpdated == null) + isInCategory = false; + // Don't include in the recently updated category if the + // 'update' was actually it being added. + else if (app.lastUpdated.compareTo(app.added) == 0) + isInCategory = false; + else if (app.lastUpdated.compareTo(recentDate) < 0) + isInCategory = false; + else + isInCategory = true; + } else { + isInCategory = category.equals(app.category); + } + return isInCategory; + } + + // Returns false if the app list is empty and the fdroid activity decided + // to attempt updating it. + private boolean updateApps() { + + allApps = ((FDroidApp)fdroidActivity.getApplication()).getApps(); + + if (allApps.isEmpty()) { + // If its the first time we've run the app, this should update + // the repos. If not, it will do nothing, presuming that the repos + // are invalid, the internet is stuffed, the sky has fallen, etc... + return fdroidActivity.updateEmptyRepos(); + } + + Date recentDate = calcMaxHistory(); + AppFilter appFilter = new AppFilter(fdroidActivity); + + Vector availApps = new Vector(); + for (DB.App app : allApps) { + + boolean isInCategory = isInCategory(app, currentCategory, recentDate); + boolean isFiltered = appFilter.filter(app); + + // Add it to the list(s). Always to installed and updates, but + // only to available if it's not filtered. + if (!isFiltered && isInCategory) + availApps.add(app); + if (app.installedVersion != null) { + installedApps.addItem(app); + if (app.hasUpdates) + canUpgradeApps.addItem(app); + } + } + + if (currentCategory.equals(categoryWhatsNew)) { + Collections.sort(availApps, new WhatsNewComparator()); + } else if (currentCategory.equals(categoryRecentlyUpdated)) { + Collections.sort(availApps, new RecentlyUpdatedComparator()); + } + + for (DB.App app : availApps) + availableApps.addItem(app); + + return true; + } + + public void setCurrentCategory(String currentCategory) { + this.currentCategory = currentCategory; + } + + static class WhatsNewComparator implements Comparator { + @Override + public int compare(DB.App lhs, DB.App rhs) { + return rhs.added.compareTo(lhs.added); + } + } + + static class RecentlyUpdatedComparator implements Comparator { + @Override + public int compare(DB.App lhs, DB.App rhs) { + return rhs.lastUpdated.compareTo(lhs.lastUpdated); + } + } +} diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java index 3b22c8f14..d66e830fa 100644 --- a/src/org/fdroid/fdroid/FDroid.java +++ b/src/org/fdroid/fdroid/FDroid.java @@ -19,46 +19,36 @@ package org.fdroid.fdroid; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.Vector; - -import android.app.*; -import android.os.Build; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; -import android.view.*; -import android.widget.*; -import org.fdroid.fdroid.DB.App; - +import android.app.ActionBar; +import android.app.AlertDialog; import android.app.AlertDialog.Builder; +import android.app.FragmentTransaction; +import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.SharedPreferences; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.ResultReceiver; -import android.preference.PreferenceManager; +import android.support.v4.app.FragmentActivity; +import android.support.v4.view.ViewPager; import android.util.Log; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView.OnItemSelectedListener; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.*; import android.widget.TabHost.TabSpec; import org.fdroid.fdroid.views.AppListFragmentPageAdapter; -import org.fdroid.fdroid.views.AppListView; -public class FDroid extends FragmentActivity implements OnItemClickListener, - OnItemSelectedListener { +public class FDroid extends FragmentActivity { - private static final int REQUEST_APPDETAILS = 0; - private static final int REQUEST_MANAGEREPOS = 1; - private static final int REQUEST_PREFS = 2; + public static final int REQUEST_APPDETAILS = 0; + public static final int REQUEST_MANAGEREPOS = 1; + public static final int REQUEST_PREFS = 2; public static final String EXTRA_TAB_UPDATE = "extraTab"; @@ -68,72 +58,33 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, private static final int ABOUT = Menu.FIRST + 3; private static final int SEARCH = Menu.FIRST + 4; - // Apps that are available to be installed - private AppListAdapter apps_av = new AppListAdapter(this); - - // Apps that are installed - private AppListAdapter apps_in = new AppListAdapter(this); - - // Apps that can be upgraded - private AppListAdapter apps_up = new AppListAdapter(this); - - // Category list - private ArrayAdapter categories; - - private String currentCategory = null; - private ProgressDialog pd; - private boolean triedEmptyUpdate; - - // List of apps. - private Vector apps = null; - private ViewPager viewPager; + private AppListManager manager = null; + // Used by pre 3.0 devices which don't have an ActionBar... private TabHost tabHost; - private AppListFragmentPageAdapter viewPageAdapter; - // The following getters - // (availableAdapter/installedAdapter/canUpdateAdapter/categoriesAdapter) - // are used by the APpListViewFactory to construct views that can be used - // either by Android 3.0+ devices with ActionBars, or earlier devices - // with old fashioned tabs. - - public AppListAdapter getAvailableAdapter() { - return apps_av; - } - - public AppListAdapter getInstalledAdapter() { - return apps_in; - } - - public AppListAdapter getCanUpdateAdapter() { - return apps_up; - } - - public ArrayAdapter getCategoriesAdapter() { - return categories; + public AppListManager getManager() { + return manager; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + manager = new AppListManager(this); setContentView(R.layout.fdroid); - - // Needs to be created before createViews(), because that will use the - // getCategoriesAdapter() accessor which expects this object... - categories = new ArrayAdapter(this, - android.R.layout.simple_spinner_item, new Vector()); - categories - .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - createViews(); createTabs(); + // Must be done *after* createViews, because it will involve a + // callback to update the tab label for the "update" tab. This + // will fail unless the tabs have actually been created. + repopulateViews(); + Intent i = getIntent(); if (i.hasExtra("uri")) { Intent call = new Intent(this, ManageRepo.class); @@ -145,16 +96,17 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, selectTab(2); } } - - triedEmptyUpdate = false; } @Override protected void onStart() { - populateLists(); super.onStart(); } + protected void repopulateViews() { + manager.repopulateLists(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -237,7 +189,6 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - triedEmptyUpdate = true; switch (requestCode) { case REQUEST_APPDETAILS: break; @@ -274,7 +225,7 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, && (data.hasExtra("reset") || data.hasExtra("update"))) { updateRepos(); } else { - populateLists(); + repopulateViews(); } break; @@ -283,7 +234,7 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, private void createViews() { viewPager = (ViewPager)findViewById(R.id.main_pager); - viewPageAdapter = new AppListFragmentPageAdapter(this); + AppListFragmentPageAdapter viewPageAdapter = new AppListFragmentPageAdapter(this); viewPager.setAdapter(viewPageAdapter); viewPager.setOnPageChangeListener( new ViewPager.SimpleOnPageChangeListener() { public void onPageSelected(int position) { @@ -308,12 +259,17 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, } } - private void updateTabText(int index) { - CharSequence text = viewPager.getAdapter().getPageTitle(index); + public void refreshUpdateTabLabel() { + final int INDEX = 2; + CharSequence text = viewPager.getAdapter().getPageTitle(INDEX); if ( Build.VERSION.SDK_INT >= 11) { - getActionBar().getTabAt(index).setText(text); + getActionBar().getTabAt(INDEX).setText(text); } else { - + // Update the count on the 'Updates' tab to show the number available. + // This is quite unpleasant, but seems to be the only way to do it. + TextView textView = (TextView) tabHost.getTabWidget().getChildAt(2) + .findViewById(android.R.id.title); + textView.setText(text); } } @@ -407,142 +363,6 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, }); } - // Populate the lists. - private void populateLists() { - - apps_in.clear(); - apps_av.clear(); - apps_up.clear(); - categories.clear(); - - long startTime = System.currentTimeMillis(); - - DB db; - String cat_all, cat_whatsnew, cat_recentlyupdated; - try { - db = DB.getDB(); - - // Populate the category list with the real categories, and the - // locally generated meta-categories for "All", "What's New" and - // "Recently Updated"... - cat_all = getString(R.string.category_all); - cat_whatsnew = getString(R.string.category_whatsnew); - cat_recentlyupdated = getString(R.string.category_recentlyupdated); - categories.add(cat_whatsnew); - categories.add(cat_recentlyupdated); - categories.add(cat_all); - for (String s : db.getCategories()) { - categories.add(s); - } - if (currentCategory == null) - currentCategory = cat_whatsnew; - - } finally { - DB.releaseDB(); - } - - apps = ((FDroidApp) getApplication()).getApps(); - - if (apps.isEmpty()) { - // Don't attempt this more than once - we may have invalid - // repositories. - if (triedEmptyUpdate) - return; - // If there are no apps, update from the repos - it must be a - // new installation. - Log.d("FDroid", "Empty app list forces repo update"); - updateRepos(); - triedEmptyUpdate = true; - return; - } - - // Calculate the cutoff date we'll use for What's New and Recently - // Updated... - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(getBaseContext()); - String sint = prefs.getString("updateHistoryDays", "14"); - int history_days = Integer.parseInt(sint); - - Calendar recent = Calendar.getInstance(); - recent.add(Calendar.DAY_OF_YEAR, -history_days); - Date recentDate = recent.getTime(); - - AppFilter appfilter = new AppFilter(this); - - boolean incat; - Vector availapps = new Vector(); - for (DB.App app : apps) { - if (currentCategory.equals(cat_all)) { - incat = true; - } else if (currentCategory.equals(cat_whatsnew)) { - if (app.added == null) - incat = false; - else if (app.added.compareTo(recentDate) < 0) - incat = false; - else - incat = true; - } else if (currentCategory.equals(cat_recentlyupdated)) { - if (app.lastUpdated == null) - incat = false; - // Don't include in the recently updated category if the - // 'update' was actually it being added. - else if (app.lastUpdated.compareTo(app.added) == 0) - incat = false; - else if (app.lastUpdated.compareTo(recentDate) < 0) - incat = false; - else - incat = true; - } else { - incat = currentCategory.equals(app.category); - } - - boolean filtered = appfilter.filter(app); - - // Add it to the list(s). Always to installed and updates, but - // only to available if it's not filtered. - if (!filtered && incat) - availapps.add(app); - if (app.installedVersion != null) { - apps_in.addItem(app); - if (app.hasUpdates) - apps_up.addItem(app); - } - } - - if (currentCategory.equals(cat_whatsnew)) { - class WhatsNewComparator implements Comparator { - @Override - public int compare(App lhs, App rhs) { - return rhs.added.compareTo(lhs.added); - } - } - Collections.sort(availapps, new WhatsNewComparator()); - } else if (currentCategory.equals(cat_recentlyupdated)) { - class UpdatedComparator implements Comparator { - @Override - public int compare(App lhs, App rhs) { - return rhs.lastUpdated.compareTo(lhs.lastUpdated); - } - } - Collections.sort(availapps, new UpdatedComparator()); - } - for (DB.App app : availapps) - apps_av.addItem(app); - - updateTabText(2); - - // Tell the lists that the data behind the adapter has changed, so - // they can refresh... - apps_av.notifyDataSetChanged(); - apps_in.notifyDataSetChanged(); - apps_up.notifyDataSetChanged(); - categories.notifyDataSetChanged(); - - Log.d("FDroid", "Updated lists - " + apps.size() + " apps in total" - + " (update took " + (System.currentTimeMillis() - startTime) - + " ms)"); - } - // For receiving results from the UpdateService when we've told it to // update in response to a user request. private class UpdateReceiver extends ResultReceiver { @@ -556,7 +376,7 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, Toast.makeText(FDroid.this, resultData.getString("errmsg"), Toast.LENGTH_LONG).show(); } else { - populateLists(); + repopulateViews(); } if (pd.isShowing()) pd.dismiss(); @@ -565,10 +385,32 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, private UpdateReceiver mUpdateReceiver; + /** + * The first time the app is run, we will have an empty app list. + * If this is the case, we will attempt to update with the default repo. + * However, if we have tried this at least once, then don't try to do + * it automatically again, because the repos or internet connection may + * be bad. + */ + public boolean updateEmptyRepos() { + final String TRIED_EMPTY_UPDATE = "triedEmptyUpdate"; + boolean hasTriedEmptyUpdate = getPreferences(MODE_PRIVATE).getBoolean(TRIED_EMPTY_UPDATE, false); + if (!hasTriedEmptyUpdate) { + Log.d("FDroid", "Empty app list, and we haven't done an update yet. Forcing repo update."); + updateRepos(); + getPreferences(MODE_PRIVATE).edit().putBoolean(TRIED_EMPTY_UPDATE, true); + return true; + } else { + Log.d("FDroid", "Empty app list, but it looks like we've had an update previously. Will not force repo update."); + return false; + } + } + // Force a repo update now. A progress dialog is shown and the UpdateService // is told to do the update, which will result in the database changing. The // UpdateReceiver class should get told when this is finished. - private void updateRepos() { + public void updateRepos() { + pd = ProgressDialog.show(this, getString(R.string.process_wait_title), getString(R.string.process_update_msg), true, true); pd.setIcon(android.R.drawable.ic_dialog_info); @@ -580,36 +422,4 @@ public class FDroid extends FragmentActivity implements OnItemClickListener, startService(intent); } - public void onItemSelected(AdapterView parent, View view, int pos, - long id) { - currentCategory = parent.getItemAtPosition(pos).toString(); - populateLists(); - } - - public void onNothingSelected(AdapterView parent) { - // We always have at least "All" - } - - // Handler for a click on one of the items in an application list. Pops - // up a dialog that shows the details of the application and all its - // available versions, with buttons to allow installation etc. - public void onItemClick(AdapterView arg0, View arg1, final int arg2, - long arg3) { - - int currentItem = viewPager.getCurrentItem(); - Fragment fragment = viewPageAdapter.getItem(currentItem); - - // The fragment.getView() returns a wrapper object which has the - // actual view we're interested in inside: - // http://stackoverflow.com/a/13684505 - ViewGroup group = (ViewGroup)fragment.getView(); - AppListView view = (AppListView)group.getChildAt(0); - final DB.App app = (DB.App)view.getAppList().getAdapter().getItem(arg2); - - Intent intent = new Intent(this, AppDetails.class); - intent.putExtra("appid", app.id); - startActivityForResult(intent, REQUEST_APPDETAILS); - - } - } diff --git a/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java b/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java index 4cbeaddb5..e817ebd29 100644 --- a/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java +++ b/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java @@ -8,6 +8,7 @@ import android.support.v4.app.FragmentPagerAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import org.fdroid.fdroid.AppListManager; import org.fdroid.fdroid.FDroid; import org.fdroid.fdroid.R; import org.fdroid.fdroid.views.fragments.AvailableAppsFragment; @@ -20,25 +21,29 @@ import org.fdroid.fdroid.views.fragments.InstalledAppsFragment; */ public class AppListFragmentPageAdapter extends FragmentPagerAdapter { - private FDroid parent; - private Fragment[] fragments = new Fragment[3]; + private FDroid parent = null; public AppListFragmentPageAdapter(FDroid parent) { super(parent.getSupportFragmentManager()); this.parent = parent; - fragments[0] = new AvailableAppsFragment().setAppListAdapter(parent.getAvailableAdapter()); - fragments[1] = new InstalledAppsFragment().setAppListAdapter(parent.getInstalledAdapter()); - fragments[2] = new CanUpdateAppsFragment().setAppListAdapter(parent.getCanUpdateAdapter()).; } @Override public Fragment getItem(int i) { - return fragments[i]; + Fragment fragment = null; + if ( i == 0 ) { + fragment = new AvailableAppsFragment(); + } else if ( i == 1 ) { + fragment = new InstalledAppsFragment(); + } else if ( i == 2 ) { + fragment = new CanUpdateAppsFragment(); + } + return fragment; } @Override public int getCount() { - return fragments.length; + return 3; } public String getPageTitle(int i) { @@ -49,7 +54,7 @@ public class AppListFragmentPageAdapter extends FragmentPagerAdapter { return parent.getString(R.string.tab_installed); case 2: String updates = parent.getString(R.string.tab_updates); - updates += " (" + parent.getCanUpdateAdapter().getCount() + ")"; + updates += " (" + parent.getManager().getCanUpdateAdapter().getCount() + ")"; return updates; default: return ""; diff --git a/src/org/fdroid/fdroid/views/fragments/AppListFragment.java b/src/org/fdroid/fdroid/views/fragments/AppListFragment.java index 45b3970ba..6ad8f9588 100644 --- a/src/org/fdroid/fdroid/views/fragments/AppListFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/AppListFragment.java @@ -1,29 +1,44 @@ package org.fdroid.fdroid.views.fragments; +import android.app.Activity; +import android.content.Intent; import android.support.v4.app.Fragment; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListView; -import org.fdroid.fdroid.AppListAdapter; +import org.fdroid.fdroid.*; import org.fdroid.fdroid.views.AppListView; abstract class AppListFragment extends Fragment implements AdapterView.OnItemClickListener { - private AppListAdapter appListAdapter; + private AppListManager appListManager; + private FDroid parent; - public AppListAdapter getAppListAdapter() { - return appListAdapter; + protected abstract AppListAdapter getAppListAdapter(); + + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + parent = (FDroid)activity; + } catch (ClassCastException e) { + // I know fragments are meant to be activity agnostic, but I can't + // think of a better way to share the one application list between + // all three app list fragments. + throw new RuntimeException( + "AppListFragment can only be attached to FDroid activity. " + + "Here it was attached to a " + activity.getClass() ); + } } - public AppListFragment setAppListAdapter(AppListAdapter adapter) { - appListAdapter = adapter; - return this; + public AppListManager getAppListManager() { + return parent.getManager(); } - protected AppListView createPlainAppList(AppListAdapter adapter) { + protected AppListView createPlainAppList() { AppListView view = new AppListView(getActivity()); - ListView list = createAppListView(adapter); + ListView list = createAppListView(); view.addView( list, new ViewGroup.LayoutParams( @@ -33,11 +48,19 @@ abstract class AppListFragment extends Fragment implements AdapterView.OnItemCli return view; } - protected ListView createAppListView(AppListAdapter adapter) { + protected ListView createAppListView() { ListView list = new ListView(getActivity()); list.setFastScrollEnabled(true); list.setOnItemClickListener(this); - list.setAdapter(adapter); + list.setAdapter(getAppListAdapter()); return list; } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final DB.App app = (DB.App)getAppListAdapter().getItem(position); + Intent intent = new Intent(getActivity(), AppDetails.class); + intent.putExtra("appid", app.id); + startActivityForResult(intent, FDroid.REQUEST_APPDETAILS); + } } diff --git a/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java b/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java index cc3b27932..517476e79 100644 --- a/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java @@ -1,17 +1,18 @@ package org.fdroid.fdroid.views.fragments; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; +import org.fdroid.fdroid.AppListAdapter; +import org.fdroid.fdroid.AppListManager; import org.fdroid.fdroid.R; import org.fdroid.fdroid.views.AppListView; public class AvailableAppsFragment extends AppListFragment implements AdapterView.OnItemSelectedListener { - private ArrayAdapter categoriesAdapter; - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { AppListView view = new AppListView(getActivity()); view.setOrientation(LinearLayout.VERTICAL); @@ -20,7 +21,7 @@ public class AvailableAppsFragment extends AppListFragment implements AdapterVie // Giving it an ID lets the default save/restore state // functionality do its stuff. spinner.setId(R.id.categorySpinner); - spinner.setAdapter(getCategoriesAdapter()); + spinner.setAdapter(getAppListManager().getCategoriesAdapter()); spinner.setOnItemSelectedListener(this); view.addView( @@ -29,7 +30,7 @@ public class AvailableAppsFragment extends AppListFragment implements AdapterVie LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); - ListView list = createAppListView(getAppListAdapter()); + ListView list = createAppListView(); view.setAppList(list); view.addView( list, @@ -48,26 +49,19 @@ public class AvailableAppsFragment extends AppListFragment implements AdapterVie super.onActivityCreated(savedInstanceState); } - public ArrayAdapter getCategoriesAdapter() { - return categoriesAdapter; - } - - public void setCategoriesAdapter(ArrayAdapter categoriesAdapter) { - this.categoriesAdapter = categoriesAdapter; - } - - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - - } - - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - + public void onItemSelected(AdapterView parent, View view, int pos, + long id) { + getAppListManager().setCurrentCategory(parent.getItemAtPosition(pos).toString()); + getAppListManager().repopulateLists(); } @Override public void onNothingSelected(AdapterView parent) { } + + @Override + protected AppListAdapter getAppListAdapter() { + return getAppListManager().getAvailableAdapter(); + } } diff --git a/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java b/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java index 33a673fd9..2b864aadd 100644 --- a/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java @@ -5,15 +5,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; +import org.fdroid.fdroid.AppListAdapter; public class CanUpdateAppsFragment extends AppListFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return createPlainAppList(getAppListAdapter()); + return createPlainAppList(); } @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - + protected AppListAdapter getAppListAdapter() { + return getAppListManager().getCanUpdateAdapter(); } } diff --git a/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java b/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java index eedb50da8..e6b48f35f 100644 --- a/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java @@ -5,15 +5,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; +import org.fdroid.fdroid.AppListAdapter; public class InstalledAppsFragment extends AppListFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return createPlainAppList(getAppListAdapter()); + return createPlainAppList(); } @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - + protected AppListAdapter getAppListAdapter() { + return getAppListManager().getInstalledAdapter(); } }