Compare commits

...

9 Commits

Author SHA1 Message Date
Daniel Martí
2a59d6b146 Bump to 0.98.1 2016-02-14 14:13:44 +00:00
Daniel Martí
5238026ce3 Update changelog for bugfix release 2016-02-14 14:12:48 +00:00
Peter Serwylo
629067d618 Use appendPath(...) instead of appendEncodedPath(...).
I misread the documentation when first using the `appendEncodedPath` method,
because it expects the path to already be encoded. This causes a bug because
if you search for a '/'. The result is a malformed URI that has the path
'/search//' instead of '/search/%2F'.

Using `appendPath` will always encode the string given to it, which is desirable.

Also check for empty strings, and return a URI that gives all apps. This was
not strictly neccesary, because the code which invokes it checks for empty
strings, but if somewhere else in the future starts to use this code, they
would've had to know to check for empty strings first.

Fixes #555.
2016-02-14 13:03:40 +00:00
Peter Serwylo
3353234786 Put null check around access of R.id.header fragment.
Please note I haven't reproduced the specific problem. Also, the stack
traces being reported are only marginally informative, because they are
in response to a content providers firing events, and thus don't have
any context about when or where the event was fired from.

However, my looking at the code seems to indicate that this will prevent
NPE when the Activity is no longer visible but an app is finished
installing. Also, the view should still update correctly on resuming the
Activity because the `onResumeFragments()` methods will be invoked
which invokes the `refreshHeaders()` method.

Fixes #286.
2016-02-06 13:43:45 +00:00
Peter Serwylo
d886789a86 Don't update search query unless it has changed meaningfully.
Changing the search query is quite an expensive operation, so this does some rudimentary
checking to see if the two queries are meaningfully different. At present, it trims the
strings and does a case insensitive comparison.

The query is eventually exploded based on whitespace, so leading and trailing white
space is not important. Also, sqlite `LIKE` clauses are case insensitive, so case
is unimportant. Having said that, I'm not sure how someone will be able to change
the queries case without first deleting and then adding characters (thus inducing
meaningfull changse).
2016-02-06 13:43:23 +00:00
Peter Serwylo
fa9e616c3f When no keywords to search, use an empty query selection that evaluates to "1".
This means that instead of building invalid SQL such as `WHERE (() OR ())` it
will build `WHERE((1) OR (1))` which, while non-optimal, is at least valid.

Fixes issue #560.
2016-02-06 13:43:15 +00:00
Daniel Micay
15499c9b31 fix AOSP build integration
The build isn't done from the top-level directory so the symlink needs
to use an absolute path.

Fixes #551.
2016-02-06 13:42:38 +00:00
Daniel Martí
1121f858c8 Avoid NPE in Uri.getPath().replaceAll()
Fixes #533.
2016-02-06 13:42:14 +00:00
Daniel Martí
e5700bc992 Bump to 0.98 2016-02-01 12:18:02 +00:00
8 changed files with 70 additions and 26 deletions

View File

@ -8,14 +8,14 @@ LOCAL_PACKAGE_NAME := F-Droid
fdroid_root := $(LOCAL_PATH) fdroid_root := $(LOCAL_PATH)
fdroid_dir := F-Droid fdroid_dir := F-Droid
fdroid_out := $(OUT_DIR)/target/common/obj/APPS/$(LOCAL_MODULE)_intermediates fdroid_out := $(PWD)/$(OUT_DIR)/target/common/obj/APPS/$(LOCAL_MODULE)_intermediates
fdroid_build := $(fdroid_root)/$(fdroid_dir)/build fdroid_build := $(fdroid_root)/$(fdroid_dir)/build
fdroid_apk := build/outputs/apk/F-Droid-release-unsigned.apk fdroid_apk := build/outputs/apk/F-Droid-release-unsigned.apk
$(fdroid_root)/$(fdroid_dir)/$(fdroid_apk): $(fdroid_root)/$(fdroid_dir)/$(fdroid_apk):
rm -Rf $(fdroid_build) rm -Rf $(fdroid_build)
mkdir -p $(fdroid_out) mkdir -p $(fdroid_out)
ln -s $(fdroid_out) $(fdroid_build) ln -sf $(fdroid_out) $(fdroid_build)
cd $(fdroid_root)/$(fdroid_dir) && gradle assembleRelease cd $(fdroid_root)/$(fdroid_dir) && gradle assembleRelease
LOCAL_CERTIFICATE := platform LOCAL_CERTIFICATE := platform

View File

@ -1,4 +1,16 @@
### 0.98 (upcoming release) ### 0.98.1 (2016-02-14)
* Fix crash when entering only a space into the search dialog
* Fix crash when entering slashes into the search dialog
* Fix potential fragment crash when installing/removing a package
* Fix crash when adding malformed URIs as repos
* Fix Android.mk build when the output dir is a relative path
### 0.98 (2016-02-01)
* Add opt-in crash reporting via ACRA * Add opt-in crash reporting via ACRA

View File

@ -3,8 +3,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="org.fdroid.fdroid" package="org.fdroid.fdroid"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="98007" android:versionCode="98150"
android:versionName="0.98-alpha7" android:versionName="0.98.1"
> >
<uses-sdk <uses-sdk

View File

@ -609,8 +609,10 @@ public class AppDetails extends AppCompatActivity implements ProgressListener, A
private void refreshHeader() { private void refreshHeader() {
mHeaderFragment = (AppDetailsHeaderFragment) mHeaderFragment = (AppDetailsHeaderFragment)
getSupportFragmentManager().findFragmentById(R.id.header); getSupportFragmentManager().findFragmentById(R.id.header);
if (mHeaderFragment != null) {
mHeaderFragment.updateViews(); mHeaderFragment.updateViews();
} }
}
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {

View File

@ -304,9 +304,9 @@ public final class Utils {
b.scheme(localRepoUri.getScheme().replaceFirst("http", "fdroidrepo")); b.scheme(localRepoUri.getScheme().replaceFirst("http", "fdroidrepo"));
b.appendQueryParameter("swap", "1"); b.appendQueryParameter("swap", "1");
if (!TextUtils.isEmpty(FDroidApp.bssid)) { if (!TextUtils.isEmpty(FDroidApp.bssid)) {
b.appendQueryParameter("bssid", Uri.encode(FDroidApp.bssid)); b.appendQueryParameter("bssid", FDroidApp.bssid);
if (!TextUtils.isEmpty(FDroidApp.ssid)) if (!TextUtils.isEmpty(FDroidApp.ssid))
b.appendQueryParameter("ssid", Uri.encode(FDroidApp.ssid)); b.appendQueryParameter("ssid", FDroidApp.ssid);
} }
return b.build(); return b.build();
} }

View File

@ -7,6 +7,7 @@ import android.content.UriMatcher;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Preferences;
@ -542,17 +543,22 @@ public class AppProvider extends FDroidProvider {
} }
public static Uri getSearchUri(String query) { public static Uri getSearchUri(String query) {
if (TextUtils.isEmpty(query)) {
// Return all the things for an empty search.
return getContentUri();
} else {
return getContentUri().buildUpon() return getContentUri().buildUpon()
.appendPath(PATH_SEARCH) .appendPath(PATH_SEARCH)
.appendEncodedPath(query) .appendPath(query)
.build(); .build();
} }
}
public static Uri getSearchInstalledUri(String query) { public static Uri getSearchInstalledUri(String query) {
return getContentUri() return getContentUri()
.buildUpon() .buildUpon()
.appendPath(PATH_SEARCH_INSTALLED) .appendPath(PATH_SEARCH_INSTALLED)
.appendEncodedPath(query) .appendPath(query)
.build(); .build();
} }
@ -560,7 +566,7 @@ public class AppProvider extends FDroidProvider {
return getContentUri() return getContentUri()
.buildUpon() .buildUpon()
.appendPath(PATH_SEARCH_CAN_UPDATE) .appendPath(PATH_SEARCH_CAN_UPDATE)
.appendEncodedPath(query) .appendPath(query)
.build(); .build();
} }
@ -568,7 +574,7 @@ public class AppProvider extends FDroidProvider {
return getContentUri().buildUpon() return getContentUri().buildUpon()
.appendPath(PATH_SEARCH_REPO) .appendPath(PATH_SEARCH_REPO)
.appendPath(repo.id + "") .appendPath(repo.id + "")
.appendEncodedPath(query) .appendPath(query)
.build(); .build();
} }
@ -614,15 +620,14 @@ public class AppProvider extends FDroidProvider {
} }
private AppQuerySelection querySearch(String query) { private AppQuerySelection querySearch(String query) {
final String[] columns = { // Put in a Set to remove duplicates
getTableName() + ".id",
getTableName() + ".name",
getTableName() + ".summary",
getTableName() + ".description",
};
// Remove duplicates, surround in % for wildcard searching
final Set<String> keywordSet = new HashSet<>(Arrays.asList(query.split("\\s"))); final Set<String> keywordSet = new HashSet<>(Arrays.asList(query.split("\\s")));
if (keywordSet.size() == 0) {
return new AppQuerySelection();
}
// Surround each keyword in % for wildcard searching
final String[] keywords = new String[keywordSet.size()]; final String[] keywords = new String[keywordSet.size()];
int iKeyword = 0; int iKeyword = 0;
for (final String keyword : keywordSet) { for (final String keyword : keywordSet) {
@ -630,6 +635,13 @@ public class AppProvider extends FDroidProvider {
iKeyword++; iKeyword++;
} }
final String[] columns = {
getTableName() + ".id",
getTableName() + ".name",
getTableName() + ".summary",
getTableName() + ".description",
};
// Build selection string and fill out keyword arguments // Build selection string and fill out keyword arguments
final StringBuilder selection = new StringBuilder(); final StringBuilder selection = new StringBuilder();
final String[] selectionKeywords = new String[columns.length * keywords.length]; final String[] selectionKeywords = new String[columns.length * keywords.length];

View File

@ -58,7 +58,22 @@ public class AppListFragmentPagerAdapter extends FragmentPagerAdapter {
return parent.getString(R.string.tab_updates_count, updateCount); return parent.getString(R.string.tab_updates_count, updateCount);
} }
/**
* Changing the search query is quite an expensive operation, so this does some rudimentary
* checking to see if the two queries are meaningfully different. At present, it trims the
* strings and does a case insensitive comparison.
*/
private boolean isSearchQuerySame(String newQuery) {
String oldValueTrimmed = searchQuery == null ? "" : searchQuery.trim();
String newValueTrimmed = newQuery == null ? "" : newQuery.trim();
return oldValueTrimmed.equalsIgnoreCase(newValueTrimmed);
}
public void updateSearchQuery(@Nullable String query) { public void updateSearchQuery(@Nullable String query) {
if (isSearchQuerySame(query)) {
return;
}
searchQuery = query; searchQuery = query;
for (AppListFragment fragment : registeredFragments) { for (AppListFragment fragment : registeredFragments) {
if (fragment != null) { if (fragment != null) {

View File

@ -583,10 +583,13 @@ public class ManageReposActivity extends ActionBarActivity {
} }
uri = uri.normalize(); uri = uri.normalize();
String path = uri.getPath().replaceAll("//*/", "/"); // Collapse multiple forward slashes into 1. String path = uri.getPath();
if (path != null) {
path = path.replaceAll("//*/", "/"); // Collapse multiple forward slashes into 1.
if (path.length() > 0 && path.charAt(path.length() - 1) == '/') { if (path.length() > 0 && path.charAt(path.length() - 1) == '/') {
path = path.substring(0, path.length() - 1); path = path.substring(0, path.length() - 1);
} }
}
return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(),
path, uri.getQuery(), uri.getFragment()).toString(); path, uri.getQuery(), uri.getFragment()).toString();