Merge commit 'refs/merge-requests/20' of git://gitorious.org/f-droid/fdroidclient into merge-requests/20
This commit is contained in:
commit
f500aad71e
@ -1,22 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/fdroid_layout"
|
||||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.v4.view.ViewPager
|
||||||
android:id="@android:id/tabhost" android:layout_width="fill_parent"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_height="fill_parent">
|
android:id="@+id/main_pager"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent">
|
||||||
|
|
||||||
<TabWidget android:id="@android:id/tabs"
|
</android.support.v4.view.ViewPager>
|
||||||
android:layout_width="fill_parent" android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<FrameLayout android:id="@android:id/tabcontent"
|
|
||||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
|
||||||
android:paddingTop="65dp">
|
|
||||||
<ListView android:id="@android:id/list" android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent" />
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</TabHost>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
234
src/org/fdroid/fdroid/AppListManager.java
Normal file
234
src/org/fdroid/fdroid/AppListManager.java
Normal file
@ -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<DB.App> allApps = null;
|
||||||
|
|
||||||
|
private FDroid fdroidActivity;
|
||||||
|
|
||||||
|
private AppListAdapter availableApps;
|
||||||
|
private AppListAdapter installedApps;
|
||||||
|
private AppListAdapter canUpgradeApps;
|
||||||
|
private ArrayAdapter<String> 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<String> 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<String>(activity,
|
||||||
|
android.R.layout.simple_spinner_item, new Vector<String>());
|
||||||
|
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<DB.App> availApps = new Vector<DB.App>();
|
||||||
|
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<DB.App> {
|
||||||
|
@Override
|
||||||
|
public int compare(DB.App lhs, DB.App rhs) {
|
||||||
|
return rhs.added.compareTo(lhs.added);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class RecentlyUpdatedComparator implements Comparator<DB.App> {
|
||||||
|
@Override
|
||||||
|
public int compare(DB.App lhs, DB.App rhs) {
|
||||||
|
return rhs.lastUpdated.compareTo(lhs.lastUpdated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
|
import android.app.ActionBar;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@ -31,43 +32,34 @@ import org.fdroid.fdroid.R;
|
|||||||
|
|
||||||
import android.R.drawable;
|
import android.R.drawable;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.app.TabActivity;
|
|
||||||
import android.app.AlertDialog.Builder;
|
import android.app.AlertDialog.Builder;
|
||||||
|
import android.app.FragmentTransaction;
|
||||||
|
import android.app.ProgressDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.ResultReceiver;
|
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.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.widget.*;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ListView;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.TabHost;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
|
||||||
import android.widget.TabHost.TabSpec;
|
import android.widget.TabHost.TabSpec;
|
||||||
|
import org.fdroid.fdroid.views.AppListFragmentPageAdapter;
|
||||||
|
|
||||||
public class FDroid extends TabActivity implements OnItemClickListener,
|
public class FDroid extends FragmentActivity {
|
||||||
OnItemSelectedListener {
|
|
||||||
|
|
||||||
private static final int REQUEST_APPDETAILS = 0;
|
public static final int REQUEST_APPDETAILS = 0;
|
||||||
private static final int REQUEST_MANAGEREPOS = 1;
|
public static final int REQUEST_MANAGEREPOS = 1;
|
||||||
private static final int REQUEST_PREFS = 2;
|
public static final int REQUEST_PREFS = 2;
|
||||||
|
|
||||||
public static final String EXTRA_TAB_UPDATE = "extraTab";
|
public static final String EXTRA_TAB_UPDATE = "extraTab";
|
||||||
|
|
||||||
@ -77,70 +69,53 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
private static final int ABOUT = Menu.FIRST + 3;
|
private static final int ABOUT = Menu.FIRST + 3;
|
||||||
private static final int SEARCH = Menu.FIRST + 4;
|
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<String> categories;
|
|
||||||
private String currentCategory = null;
|
|
||||||
|
|
||||||
private ProgressDialog pd;
|
private ProgressDialog pd;
|
||||||
|
|
||||||
// Tags for the tabs
|
private ViewPager viewPager;
|
||||||
private static final String TAB_Installed = "I";
|
|
||||||
private static final String TAB_Available = "A";
|
|
||||||
private static final String TAB_Updates = "U";
|
|
||||||
|
|
||||||
|
private AppListManager manager = null;
|
||||||
|
|
||||||
|
// Used by pre 3.0 devices which don't have an ActionBar...
|
||||||
private TabHost tabHost;
|
private TabHost tabHost;
|
||||||
private TabSpec ts;
|
|
||||||
private TabSpec ts1;
|
|
||||||
private TabSpec tsUp;
|
|
||||||
|
|
||||||
private boolean triedEmptyUpdate;
|
public AppListManager getManager() {
|
||||||
|
return manager;
|
||||||
// List of apps.
|
}
|
||||||
private Vector<DB.App> apps = null;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
manager = new AppListManager(this);
|
||||||
setContentView(R.layout.fdroid);
|
setContentView(R.layout.fdroid);
|
||||||
|
createViews();
|
||||||
categories = new ArrayAdapter<String>(this,
|
|
||||||
android.R.layout.simple_spinner_item, new Vector<String>());
|
|
||||||
categories
|
|
||||||
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
|
|
||||||
tabHost = getTabHost();
|
|
||||||
createTabs();
|
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();
|
Intent i = getIntent();
|
||||||
if (i.hasExtra("uri")) {
|
if (i.hasExtra("uri")) {
|
||||||
Intent call = new Intent(this, ManageRepo.class);
|
Intent call = new Intent(this, ManageRepo.class);
|
||||||
call.putExtra("uri", i.getStringExtra("uri"));
|
call.putExtra("uri", i.getStringExtra("uri"));
|
||||||
startActivityForResult(call, REQUEST_MANAGEREPOS);
|
startActivityForResult(call, REQUEST_MANAGEREPOS);
|
||||||
} else if (i.hasExtra(EXTRA_TAB_UPDATE)) {
|
} else if (i.hasExtra(EXTRA_TAB_UPDATE)) {
|
||||||
boolean updateTab = i.getBooleanExtra(EXTRA_TAB_UPDATE, false);
|
boolean showUpdateTab = i.getBooleanExtra(EXTRA_TAB_UPDATE, false);
|
||||||
if (updateTab) {
|
if (showUpdateTab) {
|
||||||
tabHost.setCurrentTab(2);
|
selectTab(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
triedEmptyUpdate = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
populateLists();
|
}
|
||||||
|
|
||||||
|
protected void repopulateViews() {
|
||||||
|
manager.repopulateLists();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -226,7 +201,6 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
|
||||||
triedEmptyUpdate = true;
|
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_APPDETAILS:
|
case REQUEST_APPDETAILS:
|
||||||
break;
|
break;
|
||||||
@ -263,219 +237,142 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
&& (data.hasExtra("reset") || data.hasExtra("update"))) {
|
&& (data.hasExtra("reset") || data.hasExtra("update"))) {
|
||||||
updateRepos();
|
updateRepos();
|
||||||
} else {
|
} else {
|
||||||
populateLists();
|
repopulateViews();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createTabs() {
|
private void createViews() {
|
||||||
tabHost.clearAllTabs();
|
viewPager = (ViewPager)findViewById(R.id.main_pager);
|
||||||
|
AppListFragmentPageAdapter viewPageAdapter = new AppListFragmentPageAdapter(this);
|
||||||
|
viewPager.setAdapter(viewPageAdapter);
|
||||||
|
viewPager.setOnPageChangeListener( new ViewPager.SimpleOnPageChangeListener() {
|
||||||
|
public void onPageSelected(int position) {
|
||||||
|
selectTab(position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TabContentFactory that can generate the appropriate list for each
|
private void createTabs() {
|
||||||
// tab...
|
if (Build.VERSION.SDK_INT >= 11) {
|
||||||
TabHost.TabContentFactory tf = new TabHost.TabContentFactory() {
|
createActionBarTabs();
|
||||||
|
} else {
|
||||||
|
createOldTabs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectTab(int index) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 11) {
|
||||||
|
getActionBar().setSelectedNavigationItem(index);
|
||||||
|
} else {
|
||||||
|
tabHost.setCurrentTab(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);
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createActionBarTabs() {
|
||||||
|
final ActionBar actionBar = getActionBar();
|
||||||
|
final ViewPager pager = viewPager;
|
||||||
|
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||||
|
for (int i = 0; i < viewPager.getAdapter().getCount(); i ++) {
|
||||||
|
CharSequence label = viewPager.getAdapter().getPageTitle(i);
|
||||||
|
actionBar.addTab(
|
||||||
|
actionBar.newTab()
|
||||||
|
.setText(label)
|
||||||
|
.setTabListener(new ActionBar.TabListener() {
|
||||||
|
public void onTabSelected(ActionBar.Tab tab,
|
||||||
|
FragmentTransaction ft) {
|
||||||
|
pager.setCurrentItem(tab.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There is a bit of boiler-plate code required to get a TabWidget showing,
|
||||||
|
* which includes creating a TabHost, populating it with the TabWidget,
|
||||||
|
* and giving it a FrameLayout as a child. This will make the tabs have
|
||||||
|
* dummy empty contents and then hook them up to our ViewPager.
|
||||||
|
*/
|
||||||
|
private void createOldTabs() {
|
||||||
|
tabHost = new TabHost(this);
|
||||||
|
tabHost.setLayoutParams(new TabHost.LayoutParams(
|
||||||
|
TabHost.LayoutParams.MATCH_PARENT, TabHost.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
TabWidget tabWidget = new TabWidget(this);
|
||||||
|
tabWidget.setId(android.R.id.tabs);
|
||||||
|
tabHost.setLayoutParams(new TabHost.LayoutParams(
|
||||||
|
TabWidget.LayoutParams.MATCH_PARENT, TabWidget.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
FrameLayout layout = new FrameLayout(this);
|
||||||
|
layout.setId(android.R.id.tabcontent);
|
||||||
|
layout.setLayoutParams(new TabWidget.LayoutParams(0, 0));
|
||||||
|
|
||||||
|
tabHost.addView(tabWidget);
|
||||||
|
tabHost.addView(layout);
|
||||||
|
tabHost.setup();
|
||||||
|
|
||||||
|
TabHost.TabContentFactory factory = new TabHost.TabContentFactory() {
|
||||||
@Override
|
@Override
|
||||||
public View createTabContent(String tag) {
|
public View createTabContent(String tag) {
|
||||||
|
return new View(FDroid.this);
|
||||||
AppListAdapter ad;
|
|
||||||
if (tag.equals(TAB_Installed))
|
|
||||||
ad = apps_in;
|
|
||||||
else if (tag.equals(TAB_Updates))
|
|
||||||
ad = apps_up;
|
|
||||||
else
|
|
||||||
ad = apps_av;
|
|
||||||
|
|
||||||
ListView lst = new ListView(FDroid.this);
|
|
||||||
lst.setFastScrollEnabled(true);
|
|
||||||
lst.setOnItemClickListener(FDroid.this);
|
|
||||||
lst.setAdapter(ad);
|
|
||||||
|
|
||||||
if (!tag.equals(TAB_Available))
|
|
||||||
return lst;
|
|
||||||
|
|
||||||
LinearLayout v = new LinearLayout(FDroid.this);
|
|
||||||
v.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
Spinner cats = new Spinner(FDroid.this);
|
|
||||||
// Giving it an ID lets the default save/restore state
|
|
||||||
// functionality do its stuff.
|
|
||||||
cats.setId(R.id.categorySpinner);
|
|
||||||
cats.setAdapter(categories);
|
|
||||||
cats.setOnItemSelectedListener(FDroid.this);
|
|
||||||
v.addView(cats, new LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.FILL_PARENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
|
||||||
v.addView(lst, new LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.FILL_PARENT,
|
|
||||||
LinearLayout.LayoutParams.FILL_PARENT));
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the tab of installed apps...
|
TabSpec availableTabSpec = tabHost.newTabSpec("available")
|
||||||
ts = tabHost.newTabSpec(TAB_Installed);
|
.setIndicator(
|
||||||
ts.setIndicator(getString(R.string.tab_installed), getResources()
|
getString(R.string.tab_noninstalled),
|
||||||
.getDrawable(drawable.star_off));
|
getResources().getDrawable(android.R.drawable.ic_input_add))
|
||||||
ts.setContent(tf);
|
.setContent(factory);
|
||||||
|
|
||||||
// Create the tab of apps with updates...
|
TabSpec installedTabSpec = tabHost.newTabSpec("installed")
|
||||||
tsUp = tabHost.newTabSpec(TAB_Updates);
|
.setIndicator(
|
||||||
tsUp.setIndicator(getString(R.string.tab_updates), getResources()
|
getString(R.string.tab_installed),
|
||||||
.getDrawable(drawable.star_on));
|
getResources().getDrawable(android.R.drawable.star_off))
|
||||||
tsUp.setContent(tf);
|
.setContent(factory);
|
||||||
|
|
||||||
// Create the tab of available apps...
|
TabSpec canUpdateTabSpec = tabHost.newTabSpec("canUpdate")
|
||||||
ts1 = tabHost.newTabSpec(TAB_Available);
|
.setIndicator(
|
||||||
ts1.setIndicator(getString(R.string.tab_noninstalled), getResources()
|
getString(R.string.tab_updates),
|
||||||
.getDrawable(drawable.ic_input_add));
|
getResources().getDrawable(android.R.drawable.star_on))
|
||||||
ts1.setContent(tf);
|
.setContent(factory);
|
||||||
|
|
||||||
tabHost.addTab(ts1);
|
tabHost.addTab(availableTabSpec);
|
||||||
tabHost.addTab(ts);
|
tabHost.addTab(installedTabSpec);
|
||||||
tabHost.addTab(tsUp);
|
tabHost.addTab(canUpdateTabSpec);
|
||||||
|
|
||||||
}
|
LinearLayout contentView = (LinearLayout)findViewById(R.id.fdroid_layout);
|
||||||
|
contentView.addView(tabHost, 0);
|
||||||
|
|
||||||
// Populate the lists.
|
tabHost.setOnTabChangedListener( new TabHost.OnTabChangeListener() {
|
||||||
private void populateLists() {
|
@Override
|
||||||
|
public void onTabChanged(String tabId) {
|
||||||
apps_in.clear();
|
viewPager.setCurrentItem(tabHost.getCurrentTab());
|
||||||
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<DB.App> availapps = new Vector<DB.App>();
|
|
||||||
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<DB.App> {
|
|
||||||
@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<DB.App> {
|
|
||||||
@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);
|
|
||||||
|
|
||||||
// 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 uptext = (TextView) tabHost.getTabWidget().getChildAt(2)
|
|
||||||
.findViewById(android.R.id.title);
|
|
||||||
uptext.setText(getString(R.string.tab_updates) + " ("
|
|
||||||
+ Integer.toString(apps_up.getCount()) + ")");
|
|
||||||
|
|
||||||
// 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
|
// For receiving results from the UpdateService when we've told it to
|
||||||
@ -491,7 +388,7 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
Toast.makeText(FDroid.this, resultData.getString("errmsg"),
|
Toast.makeText(FDroid.this, resultData.getString("errmsg"),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
populateLists();
|
repopulateViews();
|
||||||
}
|
}
|
||||||
if (pd.isShowing())
|
if (pd.isShowing())
|
||||||
pd.dismiss();
|
pd.dismiss();
|
||||||
@ -500,10 +397,32 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
|
|
||||||
private UpdateReceiver mUpdateReceiver;
|
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.");
|
||||||
|
getPreferences(MODE_PRIVATE).edit().putBoolean(TRIED_EMPTY_UPDATE, true).apply();
|
||||||
|
updateRepos();
|
||||||
|
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
|
// 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
|
// is told to do the update, which will result in the database changing. The
|
||||||
// UpdateReceiver class should get told when this is finished.
|
// 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),
|
pd = ProgressDialog.show(this, getString(R.string.process_wait_title),
|
||||||
getString(R.string.process_update_msg), true, true);
|
getString(R.string.process_update_msg), true, true);
|
||||||
pd.setIcon(android.R.drawable.ic_dialog_info);
|
pd.setIcon(android.R.drawable.ic_dialog_info);
|
||||||
@ -515,36 +434,4 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
|||||||
startService(intent);
|
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) {
|
|
||||||
|
|
||||||
final DB.App app;
|
|
||||||
String curtab = tabHost.getCurrentTabTag();
|
|
||||||
if (curtab.equalsIgnoreCase(TAB_Installed)) {
|
|
||||||
app = (DB.App) apps_in.getItem(arg2);
|
|
||||||
} else if (curtab.equalsIgnoreCase(TAB_Updates)) {
|
|
||||||
app = (DB.App) apps_up.getItem(arg2);
|
|
||||||
} else {
|
|
||||||
app = (DB.App) apps_av.getItem(arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent intent = new Intent(this, AppDetails.class);
|
|
||||||
intent.putExtra("appid", app.id);
|
|
||||||
startActivityForResult(intent, REQUEST_APPDETAILS);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
64
src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java
Normal file
64
src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package org.fdroid.fdroid.views;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
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;
|
||||||
|
import org.fdroid.fdroid.views.fragments.CanUpdateAppsFragment;
|
||||||
|
import org.fdroid.fdroid.views.fragments.InstalledAppsFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by the FDroid activity in conjunction with its ViewPager to support
|
||||||
|
* swiping of tabs for both old devices (< 3.0) and new devices.
|
||||||
|
*/
|
||||||
|
public class AppListFragmentPageAdapter extends FragmentPagerAdapter {
|
||||||
|
|
||||||
|
private FDroid parent = null;
|
||||||
|
|
||||||
|
public AppListFragmentPageAdapter(FDroid parent) {
|
||||||
|
super(parent.getSupportFragmentManager());
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int 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 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPageTitle(int i) {
|
||||||
|
switch(i) {
|
||||||
|
case 0:
|
||||||
|
return parent.getString(R.string.tab_noninstalled);
|
||||||
|
case 1:
|
||||||
|
return parent.getString(R.string.tab_installed);
|
||||||
|
case 2:
|
||||||
|
String updates = parent.getString(R.string.tab_updates);
|
||||||
|
updates += " (" + parent.getManager().getCanUpdateAdapter().getCount() + ")";
|
||||||
|
return updates;
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
src/org/fdroid/fdroid/views/AppListView.java
Normal file
41
src/org/fdroid/fdroid/views/AppListView.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package org.fdroid.fdroid.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There are three main app-lists in the UI:
|
||||||
|
* - Available
|
||||||
|
* - Installed
|
||||||
|
* - Apps which can be updated
|
||||||
|
* This class provides a View which knows about these app lists, but can have
|
||||||
|
* different contents (e.g. a drop down list of categories). It allows us to
|
||||||
|
* get a reference to the selected item in the FDroid Activity, without having
|
||||||
|
* to know which list we are actually looking at.
|
||||||
|
*/
|
||||||
|
public class AppListView extends LinearLayout {
|
||||||
|
|
||||||
|
private ListView appList;
|
||||||
|
|
||||||
|
public AppListView(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppListView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppListView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppList(ListView appList) {
|
||||||
|
this.appList = appList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListView getAppList() {
|
||||||
|
return appList;
|
||||||
|
}
|
||||||
|
}
|
66
src/org/fdroid/fdroid/views/fragments/AppListFragment.java
Normal file
66
src/org/fdroid/fdroid/views/fragments/AppListFragment.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
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.*;
|
||||||
|
import org.fdroid.fdroid.views.AppListView;
|
||||||
|
|
||||||
|
abstract class AppListFragment extends Fragment implements AdapterView.OnItemClickListener {
|
||||||
|
|
||||||
|
private AppListManager appListManager;
|
||||||
|
private FDroid parent;
|
||||||
|
|
||||||
|
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 AppListManager getAppListManager() {
|
||||||
|
return parent.getManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AppListView createPlainAppList() {
|
||||||
|
AppListView view = new AppListView(getActivity());
|
||||||
|
ListView list = createAppListView();
|
||||||
|
view.addView(
|
||||||
|
list,
|
||||||
|
new ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
view.setAppList(list);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ListView createAppListView() {
|
||||||
|
ListView list = new ListView(getActivity());
|
||||||
|
list.setFastScrollEnabled(true);
|
||||||
|
list.setOnItemClickListener(this);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
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 {
|
||||||
|
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
AppListView view = new AppListView(getActivity());
|
||||||
|
view.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
|
||||||
|
Spinner spinner = new Spinner(getActivity());
|
||||||
|
// Giving it an ID lets the default save/restore state
|
||||||
|
// functionality do its stuff.
|
||||||
|
spinner.setId(R.id.categorySpinner);
|
||||||
|
spinner.setAdapter(getAppListManager().getCategoriesAdapter());
|
||||||
|
spinner.setOnItemSelectedListener(this);
|
||||||
|
|
||||||
|
view.addView(
|
||||||
|
spinner,
|
||||||
|
new ViewGroup.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
ListView list = createAppListView();
|
||||||
|
view.setAppList(list);
|
||||||
|
view.addView(
|
||||||
|
list,
|
||||||
|
new ViewGroup.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.fdroid.fdroid.views.fragments;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AppListAdapter getAppListAdapter() {
|
||||||
|
return getAppListManager().getCanUpdateAdapter();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.fdroid.fdroid.views.fragments;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AppListAdapter getAppListAdapter() {
|
||||||
|
return getAppListManager().getInstalledAdapter();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user