mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-04-19 22:37:09 -04:00
[app] allow changing preferred repo in app details
This commit is contained in:
@@ -45,8 +45,12 @@ object ComposeUtils {
|
||||
)
|
||||
val newColors = (colors ?: MaterialTheme.colors).let { c ->
|
||||
if (!LocalInspectionMode.current && !c.isLight && Preferences.get().isPureBlack) {
|
||||
c.copy(background = Color.Black)
|
||||
} else c
|
||||
c.copy(background = Color.Black, surface = Color(0xff1e1e1e))
|
||||
} else if (!c.isLight) {
|
||||
c.copy(surface = Color(0xff1e1e1e))
|
||||
} else {
|
||||
c
|
||||
}
|
||||
}
|
||||
MaterialTheme(
|
||||
colors = newColors,
|
||||
@@ -111,7 +115,7 @@ object ComposeUtils {
|
||||
)
|
||||
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
|
||||
}
|
||||
Text(text = text.uppercase(Locale.getDefault()))
|
||||
Text(text = text.uppercase(Locale.getDefault()), maxLines = 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ import org.fdroid.fdroid.installer.InstallerFactory;
|
||||
import org.fdroid.fdroid.installer.InstallerService;
|
||||
import org.fdroid.fdroid.nearby.PublicSourceDirProvider;
|
||||
import org.fdroid.fdroid.views.apps.FeatureImage;
|
||||
import org.fdroid.index.RepoManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -710,6 +711,7 @@ public class AppDetailsActivity extends AppCompatActivity
|
||||
|
||||
private void onAppPrefsChanged(AppPrefs appPrefs) {
|
||||
this.appPrefs = appPrefs;
|
||||
loadRepos(appPrefs.getPreferredRepoId());
|
||||
if (app != null) updateAppInfo(app, versions, appPrefs);
|
||||
}
|
||||
|
||||
@@ -724,6 +726,20 @@ public class AppDetailsActivity extends AppCompatActivity
|
||||
supportInvalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private void loadRepos(@Nullable Long preferredRepoId) {
|
||||
Utils.runOffUiThread(() -> db.getAppDao().getRepositoryIdsForApp(packageName), repoIds -> {
|
||||
List<Repository> repoList = new ArrayList<>(repoIds.size());
|
||||
RepoManager repoManager = FDroidApp.getRepoManager(this);
|
||||
if (repoManager.getRepositories().size() <= 2) return; // don't show if only official repo+archive added
|
||||
for (long repoId: repoIds) {
|
||||
Repository repo = repoManager.getRepository(repoId);
|
||||
if (repo != null) repoList.add(repo);
|
||||
}
|
||||
long prefId = preferredRepoId == null ? app.repoId : preferredRepoId;
|
||||
adapter.setRepos(repoList, prefId);
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressLint("PackageManagerGetSignatures")
|
||||
private PackageInfo getPackageInfo(String packageName) {
|
||||
@@ -788,6 +804,16 @@ public class AppDetailsActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRepoChanged(long repoId) {
|
||||
Utils.runOffUiThread(() -> db.getAppDao().getApp(repoId, app.packageName), this::onAppChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreferredRepoChanged(long repoId) {
|
||||
FDroidApp.getRepoManager(this).setPreferredRepoId(app.packageName, repoId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall the app from the current screen. Since there are many ways
|
||||
* to uninstall an app, including from Google Play, {@code adb uninstall},
|
||||
|
||||
@@ -34,6 +34,8 @@ import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.compose.ui.platform.ComposeView;
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
@@ -49,7 +51,6 @@ import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
@@ -66,6 +67,7 @@ import org.fdroid.fdroid.installer.SessionInstallManager;
|
||||
import org.fdroid.fdroid.privileged.views.AppDiff;
|
||||
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
|
||||
import org.fdroid.fdroid.views.appdetails.AntiFeaturesListingView;
|
||||
import org.fdroid.fdroid.views.appdetails.RepoChooserKt;
|
||||
import org.fdroid.fdroid.views.main.MainActivity;
|
||||
import org.fdroid.index.v2.FileV2;
|
||||
|
||||
@@ -98,6 +100,10 @@ public class AppDetailsRecyclerViewAdapter
|
||||
void installCancel();
|
||||
|
||||
void launchApk();
|
||||
|
||||
void onRepoChanged(long repoId);
|
||||
|
||||
void onPreferredRepoChanged(long repoId);
|
||||
}
|
||||
|
||||
private static final int VIEWTYPE_HEADER = 0;
|
||||
@@ -115,6 +121,9 @@ public class AppDetailsRecyclerViewAdapter
|
||||
private final AppDetailsRecyclerViewAdapterCallbacks callbacks;
|
||||
private RecyclerView recyclerView;
|
||||
private final List<Object> items = new ArrayList<>();
|
||||
private final List<Repository> repos = new ArrayList<>();
|
||||
@Nullable
|
||||
private Long preferredRepoId = null;
|
||||
private final List<Apk> versions = new ArrayList<>();
|
||||
private final List<Apk> compatibleVersionsDifferentSigner = new ArrayList<>();
|
||||
private boolean showVersions;
|
||||
@@ -177,6 +186,13 @@ public class AppDetailsRecyclerViewAdapter
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
void setRepos(List<Repository> repos, long preferredRepoId) {
|
||||
this.repos.clear();
|
||||
this.repos.addAll(repos);
|
||||
this.preferredRepoId = preferredRepoId;
|
||||
notifyItemChanged(0); // header changed
|
||||
}
|
||||
|
||||
private void addInstalledApkIfExists(final List<Apk> apks) {
|
||||
if (app == null) return;
|
||||
Apk installedApk = app.getInstalledApk(context, apks);
|
||||
@@ -378,8 +394,7 @@ public class AppDetailsRecyclerViewAdapter
|
||||
final TextView titleView;
|
||||
final TextView authorView;
|
||||
final TextView lastUpdateView;
|
||||
final ImageView repoLogoView;
|
||||
final TextView repoNameView;
|
||||
final ComposeView repoChooserView;
|
||||
final TextView warningView;
|
||||
final TextView summaryView;
|
||||
final TextView whatsNewView;
|
||||
@@ -404,8 +419,9 @@ public class AppDetailsRecyclerViewAdapter
|
||||
titleView = view.findViewById(R.id.title);
|
||||
authorView = view.findViewById(R.id.author);
|
||||
lastUpdateView = view.findViewById(R.id.text_last_update);
|
||||
repoLogoView = view.findViewById(R.id.repo_icon);
|
||||
repoNameView = view.findViewById(R.id.repo_name);
|
||||
repoChooserView = view.findViewById(R.id.repoChooserView);
|
||||
repoChooserView.setViewCompositionStrategy(
|
||||
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed.INSTANCE);
|
||||
warningView = view.findViewById(R.id.warning);
|
||||
summaryView = view.findViewById(R.id.summary);
|
||||
whatsNewView = view.findViewById(R.id.latest);
|
||||
@@ -500,18 +516,6 @@ public class AppDetailsRecyclerViewAdapter
|
||||
if (app == null) return;
|
||||
Utils.setIconFromRepoOrPM(app, iconView, iconView.getContext());
|
||||
titleView.setText(app.name);
|
||||
Repository repo = FDroidApp.getRepoManager(context).getRepository(app.repoId);
|
||||
if (repo != null && !repo.getAddress().equals("https://f-droid.org/repo")) {
|
||||
LocaleListCompat locales = LocaleListCompat.getDefault();
|
||||
Utils.loadWithGlide(context, repo.getRepoId(), repo.getIcon(locales), repoLogoView);
|
||||
repoNameView.setText(repo.getName(locales));
|
||||
repoLogoView.setVisibility(View.VISIBLE);
|
||||
repoNameView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
Glide.with(context).clear(repoLogoView);
|
||||
repoLogoView.setVisibility(View.GONE);
|
||||
repoNameView.setVisibility(View.GONE);
|
||||
}
|
||||
if (!TextUtils.isEmpty(app.authorName)) {
|
||||
authorView.setText(context.getString(R.string.by_author_format, app.authorName));
|
||||
authorView.setVisibility(View.VISIBLE);
|
||||
@@ -534,6 +538,13 @@ public class AppDetailsRecyclerViewAdapter
|
||||
} else {
|
||||
lastUpdateView.setVisibility(View.GONE);
|
||||
}
|
||||
if (app != null && preferredRepoId != null) {
|
||||
RepoChooserKt.setContentRepoChooser(repoChooserView, repos, app.repoId, preferredRepoId,
|
||||
repo -> callbacks.onRepoChanged(repo.getRepoId()), callbacks::onPreferredRepoChanged);
|
||||
repoChooserView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
repoChooserView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (SessionInstallManager.canBeUsed(context) && suggestedApk != null
|
||||
&& !SessionInstallManager.isTargetSdkSupported(suggestedApk.targetSdkVersion)) {
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
package org.fdroid.fdroid.views.appdetails
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement.spacedBy
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.ContentAlpha
|
||||
import androidx.compose.material.DropdownMenu
|
||||
import androidx.compose.material.DropdownMenuItem
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.LocalContentAlpha
|
||||
import androidx.compose.material.LocalContentColor
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.OutlinedTextField
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextFieldDefaults
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Alignment.Companion.End
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import androidx.core.util.Consumer
|
||||
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
|
||||
import com.bumptech.glide.integration.compose.GlideImage
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import org.fdroid.database.Repository
|
||||
import org.fdroid.fdroid.R
|
||||
import org.fdroid.fdroid.Utils
|
||||
import org.fdroid.fdroid.compose.ComposeUtils.FDroidContent
|
||||
import org.fdroid.fdroid.compose.ComposeUtils.FDroidOutlineButton
|
||||
import org.fdroid.index.IndexFormatVersion.TWO
|
||||
|
||||
/**
|
||||
* A helper method to show [RepoChooser] from Java code.
|
||||
*/
|
||||
fun setContentRepoChooser(
|
||||
composeView: ComposeView,
|
||||
repos: List<Repository>,
|
||||
currentRepoId: Long,
|
||||
preferredRepoId: Long,
|
||||
onRepoChanged: Consumer<Repository>,
|
||||
onPreferredRepoChanged: Consumer<Long>,
|
||||
) {
|
||||
composeView.setContent {
|
||||
FDroidContent {
|
||||
RepoChooser(
|
||||
repos = repos,
|
||||
currentRepoId = currentRepoId,
|
||||
preferredRepoId = preferredRepoId,
|
||||
onRepoChanged = onRepoChanged::accept,
|
||||
onPreferredRepoChanged = onPreferredRepoChanged::accept,
|
||||
modifier = Modifier.background(MaterialTheme.colors.surface),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RepoChooser(
|
||||
repos: List<Repository>,
|
||||
currentRepoId: Long,
|
||||
preferredRepoId: Long,
|
||||
onRepoChanged: (Repository) -> Unit,
|
||||
onPreferredRepoChanged: (Long) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (repos.isEmpty()) {
|
||||
// no-op should not happen
|
||||
} else if (repos.size == 1) {
|
||||
RepoItem(
|
||||
repo = repos[0],
|
||||
isPreferred = false, // don't show "preferred" if the only repo anyway
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
} else {
|
||||
RepoDropDown(
|
||||
repos = repos,
|
||||
currentRepoId = currentRepoId,
|
||||
preferredRepoId = preferredRepoId,
|
||||
onRepoChanged = onRepoChanged,
|
||||
onPreferredRepoChanged = onPreferredRepoChanged,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalGlideComposeApi::class)
|
||||
private fun RepoDropDown(
|
||||
repos: List<Repository>,
|
||||
currentRepoId: Long,
|
||||
preferredRepoId: Long,
|
||||
onRepoChanged: (Repository) -> Unit,
|
||||
onPreferredRepoChanged: (Long) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val currentRepo = repos.find { it.repoId == currentRepoId }
|
||||
?: error("Current repoId not in list")
|
||||
val localeList = LocaleListCompat.getDefault()
|
||||
val res = LocalContext.current.resources
|
||||
|
||||
Column(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
) {
|
||||
Box {
|
||||
OutlinedTextField(
|
||||
value = TextFieldValue(buildAnnotatedString {
|
||||
append(currentRepo.getName(localeList) ?: "Unknown Repository")
|
||||
if (currentRepo.repoId == preferredRepoId) {
|
||||
append(" ")
|
||||
pushStyle(SpanStyle(fontWeight = FontWeight.Bold))
|
||||
append("★ ")
|
||||
append(stringResource(R.string.app_details_repository_preferred))
|
||||
}
|
||||
}),
|
||||
textStyle = MaterialTheme.typography.body2,
|
||||
onValueChange = {},
|
||||
label = {
|
||||
Text(stringResource(R.string.app_details_repositories))
|
||||
},
|
||||
leadingIcon = {
|
||||
if (LocalInspectionMode.current) Image(
|
||||
painter = rememberDrawablePainter(
|
||||
ResourcesCompat.getDrawable(res, R.drawable.ic_launcher, null)
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp),
|
||||
) else GlideImage(
|
||||
model = Utils.getDownloadRequest(
|
||||
currentRepo,
|
||||
currentRepo.getIcon(localeList)
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp),
|
||||
) {
|
||||
it.fallback(R.drawable.ic_repo_app_default)
|
||||
.error(R.drawable.ic_repo_app_default)
|
||||
}
|
||||
},
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowDropDown,
|
||||
contentDescription = stringResource(R.string.app_details_repository_expand),
|
||||
)
|
||||
},
|
||||
singleLine = true,
|
||||
enabled = false,
|
||||
colors = TextFieldDefaults.outlinedTextFieldColors( // hack to enable clickable
|
||||
disabledTextColor = LocalContentColor.current.copy(LocalContentAlpha.current),
|
||||
disabledBorderColor = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled),
|
||||
disabledLabelColor = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium),
|
||||
disabledLeadingIconColor = MaterialTheme.colors.onSurface,
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = { expanded = true }),
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
) {
|
||||
repos.iterator().forEach { repo ->
|
||||
DropdownMenuItem(onClick = {
|
||||
onRepoChanged(repo)
|
||||
expanded = false
|
||||
}) {
|
||||
RepoItem(repo, repo.repoId == preferredRepoId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentRepo.repoId != preferredRepoId) {
|
||||
FDroidOutlineButton(
|
||||
text = stringResource(R.string.app_details_repository_button_prefer),
|
||||
imageVector = Icons.Default.Star,
|
||||
onClick = { onPreferredRepoChanged(currentRepo.repoId) },
|
||||
modifier = Modifier.align(End),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalGlideComposeApi::class)
|
||||
private fun RepoItem(repo: Repository, isPreferred: Boolean, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
horizontalArrangement = spacedBy(8.dp),
|
||||
verticalAlignment = CenterVertically,
|
||||
modifier = modifier,
|
||||
) {
|
||||
val localeList = LocaleListCompat.getDefault()
|
||||
val res = LocalContext.current.resources
|
||||
if (LocalInspectionMode.current) Image(
|
||||
painter = rememberDrawablePainter(
|
||||
ResourcesCompat.getDrawable(res, R.drawable.ic_launcher, null)
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp),
|
||||
) else GlideImage(
|
||||
model = Utils.getDownloadRequest(repo, repo.getIcon(localeList)),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp),
|
||||
) {
|
||||
it.fallback(R.drawable.ic_repo_app_default).error(R.drawable.ic_repo_app_default)
|
||||
}
|
||||
Text(
|
||||
text = buildAnnotatedString {
|
||||
append(repo.getName(localeList) ?: "Unknown Repository")
|
||||
if (isPreferred) {
|
||||
append(" ")
|
||||
pushStyle(SpanStyle(fontWeight = FontWeight.Bold))
|
||||
append("★ ")
|
||||
append(stringResource(R.string.app_details_repository_preferred))
|
||||
}
|
||||
},
|
||||
style = MaterialTheme.typography.body2,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
fun RepoChooserSingleRepoPreview() {
|
||||
val repo1 = Repository(1L, "1", 1L, TWO, null, 1L, 1, 1L)
|
||||
FDroidContent {
|
||||
RepoChooser(listOf(repo1), 1L, 1L, {}, {})
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
fun RepoChooserPreview() {
|
||||
val repo1 = Repository(1L, "1", 1L, TWO, null, 1L, 1, 1L)
|
||||
val repo2 = Repository(2L, "2", 2L, TWO, null, 2L, 2, 2L)
|
||||
val repo3 = Repository(3L, "2", 3L, TWO, null, 3L, 3, 3L)
|
||||
FDroidContent {
|
||||
RepoChooser(listOf(repo1, repo2, repo3), 1L, 1L, {}, {})
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
fun RepoChooserNightPreview() {
|
||||
val repo1 = Repository(1L, "1", 1L, TWO, null, 1L, 1, 1L)
|
||||
val repo2 = Repository(2L, "2", 2L, TWO, null, 2L, 2, 2L)
|
||||
val repo3 = Repository(3L, "2", 3L, TWO, null, 3L, 3, 3L)
|
||||
FDroidContent {
|
||||
RepoChooser(listOf(repo1, repo2, repo3), 1L, 2L, {}, {})
|
||||
}
|
||||
}
|
||||
@@ -88,32 +88,13 @@
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="icon,text_last_update" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/repo_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="fitCenter"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier"
|
||||
tools:src="@drawable/ic_repo_app_default" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/repo_name"
|
||||
android:layout_width="0dp"
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/repoChooserView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="marquee"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/repo_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/repo_icon"
|
||||
app:layout_constraintTop_toTopOf="@+id/repo_icon"
|
||||
tools:text="A name of a repository with a potentially long name that wraps" />
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier"
|
||||
tools:composableName="org.fdroid.fdroid.views.appdetails.RepoChooserKt.RepoChooserPreview" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/secondaryButtonView"
|
||||
@@ -126,7 +107,7 @@
|
||||
android:ellipsize="marquee"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toStartOf="@+id/primaryButtonView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/repo_icon"
|
||||
app:layout_constraintTop_toBottomOf="@+id/repoChooserView"
|
||||
tools:text="Uninstall"
|
||||
tools:visibility="visible" />
|
||||
|
||||
@@ -140,7 +121,7 @@
|
||||
android:ellipsize="marquee"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/repo_icon"
|
||||
app:layout_constraintTop_toBottomOf="@+id/repoChooserView"
|
||||
tools:text="Open"
|
||||
tools:visibility="visible" />
|
||||
|
||||
@@ -152,7 +133,7 @@
|
||||
android:layout_marginTop="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/repo_icon"
|
||||
app:layout_constraintTop_toBottomOf="@+id/repoChooserView"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
|
||||
@@ -91,6 +91,21 @@
|
||||
|
||||
<string name="app_details">App Details</string>
|
||||
<string name="no_such_app">No such app found.</string>
|
||||
<!-- Shown above the repository an app is in -->
|
||||
<string name="app_details_repository">Repository</string>
|
||||
<!-- If an app is in more than one repository, this is shown above the selection dropdown -->
|
||||
<string name="app_details_repositories">Repositories</string>
|
||||
<!-- Shown next to the repository name of the repo that is currently preferred by the user.
|
||||
Information and updates for that app only come from the preferred repo.
|
||||
Other languages could use other words that work better in their language such as (chosen).
|
||||
-->
|
||||
<string name="app_details_repository_preferred">(preferred)</string>
|
||||
<!-- A button label. When clicked, this changes the preferred repo to the currently shown one.
|
||||
Information and updates for that app only come from the preferred repo.
|
||||
Other languages could use other words that work better in their language such as (chosen).
|
||||
-->
|
||||
<string name="app_details_repository_button_prefer">Prefer Repository</string>
|
||||
<string name="app_details_repository_expand">Expand repository list</string>
|
||||
|
||||
<string name="app_details_donate_prompt_unknown_author">Buy the developers of %1$s a coffee!</string>
|
||||
<string name="app_details_donate_prompt">%1$s is created by %2$s. Buy them a coffee!</string>
|
||||
@@ -215,7 +230,6 @@ This often occurs with apps installed via Google Play or other sources, if they
|
||||
<string name="has_disallow_install_unknown_sources_globally">Your device admin doesn\'t allow installing apps from unknown sources, that includes new repos</string>
|
||||
<!-- Message presented in a dialog box when the user restriction set by the system restricts adding new repos, e.g. "Unknown Sources". -->
|
||||
<string name="has_disallow_install_unknown_sources">Unknown sources can\'t be added by this user, that includes new repos</string>
|
||||
<string name="repo_provider">Repository: %s</string>
|
||||
|
||||
<string name="menu_manage">Repositories</string>
|
||||
<string name="repositories_summary">Add additional sources of apps</string>
|
||||
|
||||
@@ -147,6 +147,16 @@ public class AppDetailsAdapterTest {
|
||||
public void launchApk() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRepoChanged(long repoId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreferredRepoChanged(long repoId) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user