Merge branch 'category-tweaks-further' into 'master'
Category colours and sorting. Closes #1058 See merge request !539
This commit is contained in:
commit
b4d22bb4ce
@ -732,6 +732,7 @@ public class AppProvider extends FDroidProvider {
|
|||||||
case TOP_FROM_CATEGORY:
|
case TOP_FROM_CATEGORY:
|
||||||
selection = selection.add(queryCategory(pathSegments.get(2)));
|
selection = selection.add(queryCategory(pathSegments.get(2)));
|
||||||
limit = Integer.parseInt(pathSegments.get(1));
|
limit = Integer.parseInt(pathSegments.get(1));
|
||||||
|
sortOrder = getTableName() + "." + Cols.LAST_UPDATED + " DESC";
|
||||||
includeSwap = false;
|
includeSwap = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -97,6 +97,8 @@ public class CategorySpan extends ReplacementSpan {
|
|||||||
RectF backgroundRect = new RectF(0, 0, iconBackgroundSize + textLeadingPadding
|
RectF backgroundRect = new RectF(0, 0, iconBackgroundSize + textLeadingPadding
|
||||||
+ textWidth + textTrailingPadding, height);
|
+ textWidth + textTrailingPadding, height);
|
||||||
|
|
||||||
|
int backgroundColour = CategoryController.getBackgroundColour(context, categoryName.toString());
|
||||||
|
|
||||||
// The shadow below the entire category chip.
|
// The shadow below the entire category chip.
|
||||||
canvas.save();
|
canvas.save();
|
||||||
canvas.translate(0, DROP_SHADOW_HEIGHT * density);
|
canvas.translate(0, DROP_SHADOW_HEIGHT * density);
|
||||||
@ -108,7 +110,7 @@ public class CategorySpan extends ReplacementSpan {
|
|||||||
|
|
||||||
// The background which goes behind the text.
|
// The background which goes behind the text.
|
||||||
Paint backgroundPaint = new Paint();
|
Paint backgroundPaint = new Paint();
|
||||||
backgroundPaint.setColor(CategoryController.getBackgroundColour(context, categoryName.toString()));
|
backgroundPaint.setColor(backgroundColour);
|
||||||
backgroundPaint.setAntiAlias(true);
|
backgroundPaint.setAntiAlias(true);
|
||||||
canvas.drawRoundRect(backgroundRect, cornerRadius, cornerRadius, backgroundPaint);
|
canvas.drawRoundRect(backgroundRect, cornerRadius, cornerRadius, backgroundPaint);
|
||||||
|
|
||||||
@ -124,9 +126,15 @@ public class CategorySpan extends ReplacementSpan {
|
|||||||
icon.setBounds(iconPadding, iconPadding, iconPadding + iconSize, iconPadding + iconSize);
|
icon.setBounds(iconPadding, iconPadding, iconPadding + iconSize, iconPadding + iconSize);
|
||||||
icon.draw(canvas);
|
icon.draw(canvas);
|
||||||
|
|
||||||
|
// Choose white or black text based on the perceived brightness.
|
||||||
|
// Uses some arbitrary magic from https://stackoverflow.com/a/946734/2391921
|
||||||
|
double grey = Color.red(backgroundColour) * 0.299 +
|
||||||
|
Color.green(backgroundColour) * 0.587 +
|
||||||
|
Color.blue(backgroundColour) * 0.114;
|
||||||
|
|
||||||
// The category name drawn to the right of the category name.
|
// The category name drawn to the right of the category name.
|
||||||
Paint textPaint = new Paint(paint);
|
Paint textPaint = new Paint(paint);
|
||||||
textPaint.setColor(Color.WHITE);
|
textPaint.setColor(grey < 186 ? Color.WHITE : Color.BLACK);
|
||||||
canvas.drawText(categoryName.toString(), iconBackgroundSize + textLeadingPadding, bottom, textPaint);
|
canvas.drawText(categoryName.toString(), iconBackgroundSize + textLeadingPadding, bottom, textPaint);
|
||||||
|
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
|
@ -8,17 +8,17 @@
|
|||||||
<!-- Ignore UnusedResources errors here, because the resources are loaded dynamically at runtime -->
|
<!-- Ignore UnusedResources errors here, because the resources are loaded dynamically at runtime -->
|
||||||
<color tools:ignore="UnusedResources" name="category_connectivity">#CBEFEC</color>
|
<color tools:ignore="UnusedResources" name="category_connectivity">#CBEFEC</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_development">#E2D6BC</color>
|
<color tools:ignore="UnusedResources" name="category_development">#E2D6BC</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_games">#6D6862</color>
|
<color tools:ignore="UnusedResources" name="category_games">#F3B569</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_graphics">#F25050</color>
|
<color tools:ignore="UnusedResources" name="category_graphics">#F65A5A</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_internet">#DBDDC9</color>
|
<color tools:ignore="UnusedResources" name="category_internet">#73EABC</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_money">#DDDDD0</color>
|
<color tools:ignore="UnusedResources" name="category_money">#DDDDD0</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_multimedia">#FF7F66</color>
|
<color tools:ignore="UnusedResources" name="category_multimedia">#FF7F66</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_navigation">#94D6FD</color>
|
<color tools:ignore="UnusedResources" name="category_navigation">#94D6FD</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_phone_sms">#F3CFC0</color>
|
<color tools:ignore="UnusedResources" name="category_phone_sms">#F3CFC0</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_reading">#D6A07A</color>
|
<color tools:ignore="UnusedResources" name="category_reading">#D6A07A</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_science_education">#F4F4EC</color>
|
<color tools:ignore="UnusedResources" name="category_science_education">#F4F4EC</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_security">#6D6862</color>
|
<color tools:ignore="UnusedResources" name="category_security">#FFD15F</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_sports_health">#72C7EA</color>
|
<color tools:ignore="UnusedResources" name="category_sports_health">#ADCEDE</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_system">#D3DB77</color>
|
<color tools:ignore="UnusedResources" name="category_system">#D3DB77</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_theming">#DEEFE9</color>
|
<color tools:ignore="UnusedResources" name="category_theming">#DEEFE9</color>
|
||||||
<color tools:ignore="UnusedResources" name="category_time">#FF7043</color>
|
<color tools:ignore="UnusedResources" name="category_time">#FF7043</color>
|
||||||
|
@ -17,9 +17,11 @@ import org.robolectric.annotation.Config;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.fdroid.fdroid.Assert.assertContainsOnly;
|
import static org.fdroid.fdroid.Assert.assertContainsOnly;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
@Config(constants = BuildConfig.class, application = Application.class, sdk = 23)
|
@Config(constants = BuildConfig.class, application = Application.class, sdk = 23)
|
||||||
@ -164,29 +166,29 @@ public class CategoryProviderTest extends FDroidProviderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void topAppsFromCategory() {
|
public void topAppsFromCategory() {
|
||||||
insertAppWithCategory("com.dog", "Dog", "Animal");
|
insertAppWithCategory("com.dog", "Dog", "Animal", new Date(2017, 2, 6));
|
||||||
insertAppWithCategory("com.cat", "Cat", "Animal");
|
insertAppWithCategory("com.cat", "Cat", "Animal", new Date(2017, 2, 5));
|
||||||
insertAppWithCategory("com.bird", "Bird", "Animal");
|
insertAppWithCategory("com.bird", "Bird", "Animal", new Date(2017, 2, 4));
|
||||||
insertAppWithCategory("com.snake", "Snake", "Animal");
|
insertAppWithCategory("com.snake", "Snake", "Animal", new Date(2017, 2, 3));
|
||||||
insertAppWithCategory("com.rat", "Rat", "Animal");
|
insertAppWithCategory("com.rat", "Rat", "Animal", new Date(2017, 2, 2));
|
||||||
|
|
||||||
insertAppWithCategory("com.rock", "Rock", "Mineral");
|
insertAppWithCategory("com.rock", "Rock", "Mineral", new Date(2017, 1, 4));
|
||||||
insertAppWithCategory("com.stone", "Stone", "Mineral");
|
insertAppWithCategory("com.stone", "Stone", "Mineral", new Date(2017, 1, 3));
|
||||||
insertAppWithCategory("com.boulder", "Boulder", "Mineral");
|
insertAppWithCategory("com.boulder", "Boulder", "Mineral", new Date(2017, 1, 2));
|
||||||
|
|
||||||
insertAppWithCategory("com.banana", "Banana", "Vegetable");
|
insertAppWithCategory("com.banana", "Banana", "Vegetable", new Date(2015, 1, 1));
|
||||||
insertAppWithCategory("com.tomato", "Tomato", "Vegetable");
|
insertAppWithCategory("com.tomato", "Tomato", "Vegetable", new Date(2017, 4, 4));
|
||||||
|
|
||||||
assertContainsOnly(topAppsFromCategory("Animal", 3), new String[]{"com.bird", "com.cat", "com.dog"});
|
assertArrayEquals(getTopAppsFromCategory("Animal", 3), new String[]{"com.dog", "com.cat", "com.bird"});
|
||||||
assertContainsOnly(topAppsFromCategory("Animal", 2), new String[]{"com.bird", "com.cat"});
|
assertArrayEquals(getTopAppsFromCategory("Animal", 2), new String[]{"com.dog", "com.cat"});
|
||||||
assertContainsOnly(topAppsFromCategory("Animal", 1), new String[]{"com.bird"});
|
assertArrayEquals(getTopAppsFromCategory("Animal", 1), new String[]{"com.dog"});
|
||||||
|
|
||||||
assertContainsOnly(topAppsFromCategory("Mineral", 2), new String[]{"com.boulder", "com.rock"});
|
assertArrayEquals(getTopAppsFromCategory("Mineral", 2), new String[]{"com.rock", "com.stone"});
|
||||||
|
|
||||||
assertContainsOnly(topAppsFromCategory("Vegetable", 10), new String[]{"com.banana", "com.tomato"});
|
assertArrayEquals(getTopAppsFromCategory("Vegetable", 10), new String[]{"com.tomato", "com.banana"});
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] topAppsFromCategory(String category, int numToGet) {
|
public String[] getTopAppsFromCategory(String category, int numToGet) {
|
||||||
List<App> apps = AppProvider.Helper.cursorToList(contentResolver
|
List<App> apps = AppProvider.Helper.cursorToList(contentResolver
|
||||||
.query(AppProvider.getTopFromCategoryUri(category, numToGet), Cols.ALL, null, null, Cols.NAME));
|
.query(AppProvider.getTopFromCategoryUri(category, numToGet), Cols.ALL, null, null, Cols.NAME));
|
||||||
String[] packageNames = new String[apps.size()];
|
String[] packageNames = new String[apps.size()];
|
||||||
@ -260,12 +262,21 @@ public class CategoryProviderTest extends FDroidProviderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void insertAppWithCategory(String id, String name, String categories) {
|
private void insertAppWithCategory(String id, String name, String categories) {
|
||||||
insertAppWithCategory(id, name, categories, 1);
|
insertAppWithCategory(id, name, categories, new Date(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertAppWithCategory(String id, String name, String categories, Date lastUpdated) {
|
||||||
|
insertAppWithCategory(id, name, categories, lastUpdated, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertAppWithCategory(String id, String name, String categories, long repoId) {
|
private void insertAppWithCategory(String id, String name, String categories, long repoId) {
|
||||||
ContentValues values = new ContentValues(1);
|
insertAppWithCategory(id, name, categories, new Date(), repoId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertAppWithCategory(String id, String name, String categories, Date lastUpdated, long repoId) {
|
||||||
|
ContentValues values = new ContentValues(2);
|
||||||
values.put(Cols.ForWriting.Categories.CATEGORIES, categories);
|
values.put(Cols.ForWriting.Categories.CATEGORIES, categories);
|
||||||
|
values.put(Cols.LAST_UPDATED, lastUpdated.getTime() / 1000);
|
||||||
AppProviderTest.insertApp(contentResolver, context, id, name, values, repoId);
|
AppProviderTest.insertApp(contentResolver, context, id, name, values, repoId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user