Merge branch '0.103-alpha3--ui-fixes' into 'master'
0.103-alpha3 UI fixes Closes #981, #967, and #965 See merge request !490
This commit is contained in:
commit
f8c9d7ec8e
@ -279,8 +279,7 @@ public class FDroidApp extends Application {
|
|||||||
new FileNameGenerator() {
|
new FileNameGenerator() {
|
||||||
@Override
|
@Override
|
||||||
public String generate(String imageUri) {
|
public String generate(String imageUri) {
|
||||||
return imageUri.substring(
|
return imageUri.substring(imageUri.lastIndexOf('/') + 1);
|
||||||
imageUri.lastIndexOf('/') + 1);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 30 days in secs: 30*24*60*60 = 2592000
|
// 30 days in secs: 30*24*60*60 = 2592000
|
||||||
|
@ -531,7 +531,10 @@ class NotificationHelper {
|
|||||||
// Need to check that the notification is still valid, and also that the image
|
// Need to check that the notification is still valid, and also that the image
|
||||||
// is indeed cached now, so we won't get stuck in an endless loop.
|
// is indeed cached now, so we won't get stuck in an endless loop.
|
||||||
AppUpdateStatusManager.AppUpdateStatus oldEntry = appUpdateStatusManager.get(entry.getUniqueKey());
|
AppUpdateStatusManager.AppUpdateStatus oldEntry = appUpdateStatusManager.get(entry.getUniqueKey());
|
||||||
if (oldEntry != null && DiskCacheUtils.findInCache(oldEntry.app.iconUrl, ImageLoader.getInstance().getDiskCache()) != null) {
|
if (oldEntry != null
|
||||||
|
&& oldEntry.app != null
|
||||||
|
&& oldEntry.app.iconUrl != null
|
||||||
|
&& DiskCacheUtils.findInCache(oldEntry.app.iconUrl, ImageLoader.getInstance().getDiskCache()) != null) {
|
||||||
createNotification(oldEntry); // Update with new image!
|
createNotification(oldEntry); // Update with new image!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -696,6 +696,7 @@ public class AppProvider extends FDroidProvider {
|
|||||||
|
|
||||||
case INSTALLED:
|
case INSTALLED:
|
||||||
selection = selection.add(queryInstalled());
|
selection = selection.add(queryInstalled());
|
||||||
|
sortOrder = Cols.NAME;
|
||||||
includeSwap = false;
|
includeSwap = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import android.content.pm.PackageInfo;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.Signature;
|
import android.content.pm.Signature;
|
||||||
|
|
||||||
|
import org.acra.ACRA;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
@ -51,6 +52,15 @@ class ApkSignatureVerifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasFDroidSignature(File apkFile) {
|
public boolean hasFDroidSignature(File apkFile) {
|
||||||
|
if (!apkFile.exists()) {
|
||||||
|
ACRA.getErrorReporter().handleException(
|
||||||
|
new Exception("Failed to install Privileged Extension, because " + apkFile.getAbsolutePath() + " does not exist."),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] apkSig = getApkSignature(apkFile);
|
byte[] apkSig = getApkSignature(apkFile);
|
||||||
byte[] fdroidSig = getFDroidSignature();
|
byte[] fdroidSig = getFDroidSignature();
|
||||||
|
|
||||||
@ -66,7 +76,15 @@ class ApkSignatureVerifier {
|
|||||||
|
|
||||||
private byte[] getApkSignature(File apkFile) {
|
private byte[] getApkSignature(File apkFile) {
|
||||||
final String pkgPath = apkFile.getAbsolutePath();
|
final String pkgPath = apkFile.getAbsolutePath();
|
||||||
|
if (!apkFile.exists()) {
|
||||||
|
throw new IllegalArgumentException("Could not find APK at \"" + pkgPath + "\" when checking for signature.");
|
||||||
|
}
|
||||||
|
|
||||||
PackageInfo pkgInfo = pm.getPackageArchiveInfo(pkgPath, PackageManager.GET_SIGNATURES);
|
PackageInfo pkgInfo = pm.getPackageArchiveInfo(pkgPath, PackageManager.GET_SIGNATURES);
|
||||||
|
if (pkgInfo == null) {
|
||||||
|
throw new IllegalArgumentException("Could not find PackageInfo for package at \"" + pkgPath + "\".");
|
||||||
|
}
|
||||||
|
|
||||||
return signatureToBytes(pkgInfo.signatures);
|
return signatureToBytes(pkgInfo.signatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,17 +372,21 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
progressBar.setMax(totalBytes);
|
progressBar.setMax(totalBytes);
|
||||||
progressBar.setProgress(bytesDownloaded);
|
progressBar.setProgress(bytesDownloaded);
|
||||||
progressBar.setIndeterminate(totalBytes == -1);
|
progressBar.setIndeterminate(totalBytes == -1);
|
||||||
|
progressLabel.setContentDescription("");
|
||||||
if (resIdString != 0) {
|
if (resIdString != 0) {
|
||||||
progressLabel.setText(resIdString);
|
progressLabel.setText(resIdString);
|
||||||
|
progressLabel.setContentDescription(context.getString(R.string.downloading));
|
||||||
progressPercent.setText("");
|
progressPercent.setText("");
|
||||||
} else if (totalBytes > 0 && bytesDownloaded >= 0) {
|
} else if (totalBytes > 0 && bytesDownloaded >= 0) {
|
||||||
float percent = bytesDownloaded * 100 / totalBytes;
|
float percent = bytesDownloaded * 100 / totalBytes;
|
||||||
progressLabel.setText(Utils.getFriendlySize(bytesDownloaded) + " / " + Utils.getFriendlySize(totalBytes));
|
progressLabel.setText(Utils.getFriendlySize(bytesDownloaded) + " / " + Utils.getFriendlySize(totalBytes));
|
||||||
|
progressLabel.setContentDescription(context.getString(R.string.app__tts__downloading_progress, (int) percent));
|
||||||
NumberFormat format = NumberFormat.getPercentInstance();
|
NumberFormat format = NumberFormat.getPercentInstance();
|
||||||
format.setMaximumFractionDigits(0);
|
format.setMaximumFractionDigits(0);
|
||||||
progressPercent.setText(format.format(percent / 100));
|
progressPercent.setText(format.format(percent / 100));
|
||||||
} else if (bytesDownloaded >= 0) {
|
} else if (bytesDownloaded >= 0) {
|
||||||
progressLabel.setText(Utils.getFriendlySize(bytesDownloaded));
|
progressLabel.setText(Utils.getFriendlySize(bytesDownloaded));
|
||||||
|
progressLabel.setContentDescription(context.getString(R.string.downloading));
|
||||||
progressPercent.setText("");
|
progressPercent.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +322,11 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
actionButton.setVisibility(View.VISIBLE);
|
actionButton.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
if (wasSuccessfullyInstalled(app) != null) {
|
if (wasSuccessfullyInstalled(app) != null) {
|
||||||
|
if (activity.getPackageManager().getLaunchIntentForPackage(currentApp.packageName) != null) {
|
||||||
actionButton.setText(R.string.menu_launch);
|
actionButton.setText(R.string.menu_launch);
|
||||||
|
} else {
|
||||||
|
actionButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
} else if (isReadyToInstall(app)) {
|
} else if (isReadyToInstall(app)) {
|
||||||
if (app.isInstalled()) {
|
if (app.isInstalled()) {
|
||||||
actionButton.setText(R.string.app__install_downloaded_update);
|
actionButton.setText(R.string.app__install_downloaded_update);
|
||||||
@ -520,12 +524,14 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
AppUpdateStatusManager.AppUpdateStatus successfullyInstalledStatus = wasSuccessfullyInstalled(currentApp);
|
AppUpdateStatusManager.AppUpdateStatus successfullyInstalledStatus = wasSuccessfullyInstalled(currentApp);
|
||||||
if (successfullyInstalledStatus != null) {
|
if (successfullyInstalledStatus != null) {
|
||||||
Intent intent = activity.getPackageManager().getLaunchIntentForPackage(currentApp.packageName);
|
Intent intent = activity.getPackageManager().getLaunchIntentForPackage(currentApp.packageName);
|
||||||
|
if (intent != null) {
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
|
|
||||||
// Once it is explicitly launched by the user, then we can pretty much forget about
|
// Once it is explicitly launched by the user, then we can pretty much forget about
|
||||||
// any sort of notification that the app was successfully installed. It should be
|
// any sort of notification that the app was successfully installed. It should be
|
||||||
// apparent to the user because they just launched it.
|
// apparent to the user because they just launched it.
|
||||||
AppUpdateStatusManager.getInstance(activity).removeApk(successfullyInstalledStatus.getUniqueKey());
|
AppUpdateStatusManager.getInstance(activity).removeApk(successfullyInstalledStatus.getUniqueKey());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
package org.fdroid.fdroid.views.categories;
|
package org.fdroid.fdroid.views.categories;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.database.Cursor;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.LoaderManager;
|
import android.support.v4.app.LoaderManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.data.Schema;
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class CategoryAdapter extends RecyclerView.Adapter<CategoryController> {
|
public class CategoryAdapter extends RecyclerView.Adapter<CategoryController> {
|
||||||
|
|
||||||
private Cursor cursor;
|
@NonNull
|
||||||
|
private List<String> unlocalizedCategoryNames = Collections.<String>emptyList();
|
||||||
|
|
||||||
private final Activity activity;
|
private final Activity activity;
|
||||||
private final LoaderManager loaderManager;
|
private final LoaderManager loaderManager;
|
||||||
|
|
||||||
@ -27,17 +31,16 @@ public class CategoryAdapter extends RecyclerView.Adapter<CategoryController> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(CategoryController holder, int position) {
|
public void onBindViewHolder(CategoryController holder, int position) {
|
||||||
cursor.moveToPosition(position);
|
holder.bindModel(unlocalizedCategoryNames.get(position));
|
||||||
holder.bindModel(cursor.getString(cursor.getColumnIndex(Schema.CategoryTable.Cols.NAME)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return cursor == null ? 0 : cursor.getCount();
|
return unlocalizedCategoryNames.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCategoriesCursor(Cursor cursor) {
|
public void setCategories(@NonNull List<String> unlocalizedCategoryNames) {
|
||||||
this.cursor = cursor;
|
this.unlocalizedCategoryNames = unlocalizedCategoryNames;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,11 +75,15 @@ public class CategoryController extends RecyclerView.ViewHolder implements Loade
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String translateCategory(Context context, String categoryName) {
|
||||||
|
int categoryNameId = getCategoryResource(context, categoryName, "string", false);
|
||||||
|
return categoryNameId == 0 ? categoryName : context.getString(categoryNameId);
|
||||||
|
}
|
||||||
|
|
||||||
void bindModel(@NonNull String categoryName) {
|
void bindModel(@NonNull String categoryName) {
|
||||||
currentCategory = categoryName;
|
currentCategory = categoryName;
|
||||||
|
|
||||||
int categoryNameId = getCategoryResource(activity, categoryName, "string", false);
|
String translatedName = translateCategory(activity, categoryName);
|
||||||
String translatedName = categoryNameId == 0 ? categoryName : activity.getString(categoryNameId);
|
|
||||||
heading.setText(translatedName);
|
heading.setText(translatedName);
|
||||||
heading.setContentDescription(activity.getString(R.string.tts_category_name, translatedName));
|
heading.setContentDescription(activity.getString(R.string.tts_category_name, translatedName));
|
||||||
|
|
||||||
|
@ -19,6 +19,12 @@ import org.fdroid.fdroid.data.CategoryProvider;
|
|||||||
import org.fdroid.fdroid.data.Schema;
|
import org.fdroid.fdroid.data.Schema;
|
||||||
import org.fdroid.fdroid.views.apps.AppListActivity;
|
import org.fdroid.fdroid.views.apps.AppListActivity;
|
||||||
import org.fdroid.fdroid.views.categories.CategoryAdapter;
|
import org.fdroid.fdroid.views.categories.CategoryAdapter;
|
||||||
|
import org.fdroid.fdroid.views.categories.CategoryController;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for ensuring that the categories view is inflated and then populated correctly.
|
* Responsible for ensuring that the categories view is inflated and then populated correctly.
|
||||||
@ -75,13 +81,38 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads all categories from the cursor and stores them in memory to provide to the {@link CategoryAdapter}.
|
||||||
|
*
|
||||||
|
* It does this so it is easier to deal with localized/unlocalized categories without having
|
||||||
|
* to store the localized version in the database. It is not expected that the list of categories
|
||||||
|
* will grow so large as to make this a performance concern. If it does in the future, the
|
||||||
|
* {@link CategoryAdapter} can be reverted to wrap the cursor again, and localized category
|
||||||
|
* names can be stored in the database (allowing sorting in their localized form).
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||||
if (loader.getId() != LOADER_ID) {
|
if (loader.getId() != LOADER_ID || cursor == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
categoryAdapter.setCategoriesCursor(cursor);
|
List<String> categoryNames = new ArrayList<>(cursor.getCount());
|
||||||
|
cursor.moveToFirst();
|
||||||
|
while (!cursor.isAfterLast()) {
|
||||||
|
categoryNames.add(cursor.getString(cursor.getColumnIndex(Schema.CategoryTable.Cols.NAME)));
|
||||||
|
cursor.moveToNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(categoryNames, new Comparator<String>() {
|
||||||
|
@Override
|
||||||
|
public int compare(String categoryOne, String categoryTwo) {
|
||||||
|
String localizedCategoryOne = CategoryController.translateCategory(activity, categoryOne);
|
||||||
|
String localizedCategoryTwo = CategoryController.translateCategory(activity, categoryTwo);
|
||||||
|
return localizedCategoryOne.compareTo(localizedCategoryTwo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
categoryAdapter.setCategories(categoryNames);
|
||||||
|
|
||||||
if (categoryAdapter.getItemCount() == 0) {
|
if (categoryAdapter.getItemCount() == 0) {
|
||||||
emptyState.setVisibility(View.VISIBLE);
|
emptyState.setVisibility(View.VISIBLE);
|
||||||
@ -90,6 +121,8 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
emptyState.setVisibility(View.GONE);
|
emptyState.setVisibility(View.GONE);
|
||||||
categoriesList.setVisibility(View.VISIBLE);
|
categoriesList.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -98,7 +131,7 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
categoryAdapter.setCategoriesCursor(null);
|
categoryAdapter.setCategories(Collections.<String>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,13 @@
|
|||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<!-- Icon, Name, Author (optional), Updated date -->
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/icon_and_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/icon"
|
||||||
android:layout_width="72dp"
|
android:layout_width="72dp"
|
||||||
@ -33,11 +40,11 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:paddingRight="8dp"
|
android:paddingRight="8dp"
|
||||||
android:paddingEnd="8dp"
|
android:paddingEnd="8dp"
|
||||||
android:src="@drawable/ic_repo_app_default" />
|
android:src="@drawable/ic_repo_app_default" />
|
||||||
|
|
||||||
|
<!-- Name, Author (optional), Updated date -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -54,7 +61,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@style/DetailsAppTitleStyle"
|
android:textAppearance="@style/DetailsAppTitleStyle"
|
||||||
tools:text="App Title" />
|
tools:text="Really Long App Title Which Wraps Around Onto the Second Line" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/author"
|
android:id="@+id/author"
|
||||||
@ -73,6 +80,9 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<!-- Progress info -->
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/progress_layout"
|
android:id="@+id/progress_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -81,7 +91,8 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@id/icon">
|
android:layout_below="@id/icon_and_name"
|
||||||
|
tools:visibility="gone">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/progress_cancel"
|
android:id="@+id/progress_cancel"
|
||||||
@ -90,6 +101,7 @@
|
|||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@string/app__tts__cancel_download"
|
||||||
android:src="@android:drawable/ic_menu_close_clear_cancel" />
|
android:src="@android:drawable/ic_menu_close_clear_cancel" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -99,6 +111,8 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:text="@string/downloading"
|
android:text="@string/downloading"
|
||||||
|
android:contentDescription="@string/downloading"
|
||||||
|
android:focusable="true"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -122,18 +136,19 @@
|
|||||||
android:layout_toStartOf="@id/progress_cancel" />
|
android:layout_toStartOf="@id/progress_cancel" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<!-- Install, Uninstall, Upgrade, Run buttons -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/button_layout"
|
android:id="@+id/button_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/icon"
|
android:layout_below="@id/icon_and_name"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:paddingBottom="2dp"
|
android:paddingBottom="2dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:visibility="gone"
|
android:visibility="visible"
|
||||||
>
|
>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
<string name="app_recommended_version_installed">Version %1$s (Recommended)</string>
|
<string name="app_recommended_version_installed">Version %1$s (Recommended)</string>
|
||||||
<string name="app__newly_added">New</string>
|
<string name="app__newly_added">New</string>
|
||||||
<string name="added_on">Added on %s</string>
|
<string name="added_on">Added on %s</string>
|
||||||
|
<string name="app__tts__cancel_download">Cancel download</string>
|
||||||
<string name="app__install_downloaded_update">Update</string>
|
<string name="app__install_downloaded_update">Update</string>
|
||||||
|
|
||||||
<string name="app_list__name__downloaded_and_ready_to_update">Update %1$s</string>
|
<string name="app_list__name__downloaded_and_ready_to_update">Update %1$s</string>
|
||||||
@ -475,6 +476,7 @@
|
|||||||
<string name="perms_new_perm_prefix">New:</string>
|
<string name="perms_new_perm_prefix">New:</string>
|
||||||
<string name="perms_description_app">Provided by %1$s.</string>
|
<string name="perms_description_app">Provided by %1$s.</string>
|
||||||
<string name="downloading">Downloading…</string>
|
<string name="downloading">Downloading…</string>
|
||||||
|
<string name="app__tts__downloading_progress">Downloading, %1$d%% complete</string>
|
||||||
<string name="downloading_apk">Downloading %1$s</string>
|
<string name="downloading_apk">Downloading %1$s</string>
|
||||||
<string name="installing">Installing…</string>
|
<string name="installing">Installing…</string>
|
||||||
<string name="uninstalling">Uninstalling…</string>
|
<string name="uninstalling">Uninstalling…</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user