[app] Add fab to add modules to other users (#603)
This commit is contained in:
parent
dc8deae175
commit
ce0a095a7a
|
|
@ -240,7 +240,7 @@ public class ConfigManager {
|
|||
}
|
||||
|
||||
public static boolean installExistingPackageAsUser(String packageName, int userId) {
|
||||
int INSTALL_SUCCEEDED = 1;
|
||||
final int INSTALL_SUCCEEDED = 1;
|
||||
try {
|
||||
var ret = LSPManagerServiceClient.installExistingPackageAsUser(packageName, userId);
|
||||
return ret == INSTALL_SUCCEEDED;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ import android.text.style.ForegroundColorSpan;
|
|||
import android.text.style.StyleSpan;
|
||||
import android.text.style.TypefaceSpan;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
|
@ -60,6 +59,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
|
|
@ -72,6 +72,7 @@ import org.lsposed.manager.App;
|
|||
import org.lsposed.manager.BuildConfig;
|
||||
import org.lsposed.manager.ConfigManager;
|
||||
import org.lsposed.manager.R;
|
||||
import org.lsposed.manager.databinding.ItemModuleBinding;
|
||||
import org.lsposed.manager.ui.activity.AppListActivity;
|
||||
import org.lsposed.manager.ui.fragment.CompileDialogFragment;
|
||||
import org.lsposed.manager.util.GlideApp;
|
||||
|
|
@ -149,8 +150,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(activity).inflate(R.layout.item_module, parent, false);
|
||||
return new ViewHolder(v);
|
||||
return new ViewHolder(ItemModuleBinding.inflate(activity.getLayoutInflater(), parent, false));
|
||||
}
|
||||
|
||||
private boolean shouldHideApp(PackageInfo info, ApplicationWithEquals app) {
|
||||
|
|
@ -559,20 +559,19 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
View root;
|
||||
ConstraintLayout root;
|
||||
ImageView appIcon;
|
||||
TextView appName;
|
||||
TextView appDescription;
|
||||
MaterialCheckBox checkbox;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
root = itemView.findViewById(R.id.item_root);
|
||||
appIcon = itemView.findViewById(R.id.app_icon);
|
||||
appName = itemView.findViewById(R.id.app_name);
|
||||
appDescription = itemView.findViewById(R.id.description);
|
||||
checkbox = itemView.findViewById(R.id.checkbox);
|
||||
ViewHolder(ItemModuleBinding binding) {
|
||||
super(binding.getRoot());
|
||||
root = binding.itemRoot;
|
||||
appIcon = binding.appIcon;
|
||||
appName = binding.appName;
|
||||
appDescription = binding.description;
|
||||
checkbox = binding.checkbox;
|
||||
checkbox.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ import android.text.TextUtils;
|
|||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.text.style.TypefaceSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
|
@ -57,6 +56,7 @@ import androidx.annotation.Nullable;
|
|||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
|
@ -64,6 +64,8 @@ import androidx.viewpager2.widget.ViewPager2;
|
|||
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
|
|
@ -71,6 +73,7 @@ import org.lsposed.manager.ConfigManager;
|
|||
import org.lsposed.manager.R;
|
||||
import org.lsposed.manager.adapters.AppHelper;
|
||||
import org.lsposed.manager.databinding.ActivityModuleDetailBinding;
|
||||
import org.lsposed.manager.databinding.ItemModuleBinding;
|
||||
import org.lsposed.manager.databinding.ItemRepoRecyclerviewBinding;
|
||||
import org.lsposed.manager.repo.RepoLoader;
|
||||
import org.lsposed.manager.ui.activity.base.BaseActivity;
|
||||
|
|
@ -83,6 +86,7 @@ import java.util.ArrayList;
|
|||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import rikka.core.res.ResourcesKt;
|
||||
|
|
@ -133,8 +137,31 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
if (recyclerView != null) {
|
||||
binding.appBar.setRaised(!recyclerView.getBorderViewDelegate().isShowingTopBorder());
|
||||
}
|
||||
if (position > 0) binding.fab.show();
|
||||
else binding.fab.hide();
|
||||
}
|
||||
});
|
||||
binding.fab.setOnClickListener(view -> {
|
||||
var pickAdaptor = new ModuleAdapter(0, null, true);
|
||||
var position = binding.viewPager.getCurrentItem();
|
||||
var snapshot = adapters.get(position).snapshot().stream().map(m -> m.packageName).collect(Collectors.toSet());
|
||||
var userId = adapters.get(position).getUserId();
|
||||
pickAdaptor.setFilter(m -> !snapshot.contains(m.packageName));
|
||||
pickAdaptor.refresh();
|
||||
var v = new RecyclerView(ModulesActivity.this);
|
||||
v.setAdapter(pickAdaptor);
|
||||
v.setLayoutManager(new LinearLayoutManagerFix(ModulesActivity.this));
|
||||
var dialog = new AlertDialog.Builder(ModulesActivity.this)
|
||||
.setTitle(getString(R.string.install_to_user, userId))
|
||||
.setView(v)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
pickAdaptor.setOnPickListener(picked -> {
|
||||
var module = (ModuleUtil.InstalledModule) picked.getTag();
|
||||
installModuleToUser(module, userId);
|
||||
dialog.dismiss();
|
||||
});
|
||||
});
|
||||
mSearchListener = new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
|
|
@ -191,12 +218,6 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
ArrayList<String> titles = new ArrayList<>();
|
||||
for (int userId : userIds) {
|
||||
var adapter = new ModuleAdapter(userId, handles.get(userId));
|
||||
if (userId == 0) {
|
||||
adapter.setProfiles(users.stream()
|
||||
.filter(u -> u.hashCode() != 0)
|
||||
.mapToInt(UserHandle::hashCode)
|
||||
.toArray());
|
||||
}
|
||||
adapter.setHasStableIds(true);
|
||||
adapters.add(adapter);
|
||||
titles.add(getString(R.string.user_title, userId));
|
||||
|
|
@ -244,6 +265,28 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void installModuleToUser(ModuleUtil.InstalledModule module, int userId) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.install_to_user, userId))
|
||||
.setMessage(getString(R.string.install_to_user_message, module.getAppName(), userId))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) ->
|
||||
workHandler.post(() -> {
|
||||
var success = ConfigManager.installExistingPackageAsUser(module.packageName, userId);
|
||||
runOnUiThread(() -> {
|
||||
String text = success ? getString(R.string.module_installed, module.getAppName(), userId) : getString(R.string.module_install_failed);
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
|
||||
Snackbar.make(binding.snackbar, text, Snackbar.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(ModulesActivity.this, text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
if (success)
|
||||
moduleUtil.reloadSingleModule(module.packageName, userId);
|
||||
}))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
||||
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().getModule(selectedModule.packageName, selectedModule.userId);
|
||||
|
|
@ -305,25 +348,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
startActivity(intent);
|
||||
return true;
|
||||
} else if (item.getGroupId() == 1) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.install_to_user, itemId))
|
||||
.setMessage(getString(R.string.install_to_user_message, module.getAppName(), itemId))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) ->
|
||||
workHandler.post(() -> {
|
||||
var success = ConfigManager.installExistingPackageAsUser(module.packageName, itemId);
|
||||
runOnUiThread(() -> {
|
||||
String text = success ? getString(R.string.module_installed, module.getAppName()) : getString(R.string.module_install_failed);
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
|
||||
Snackbar.make(binding.snackbar, text, Snackbar.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(ModulesActivity.this, text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
if (success)
|
||||
moduleUtil.reloadSingleModule(module.packageName, itemId);
|
||||
}))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
installModuleToUser(module, itemId);
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
|
|
@ -334,7 +359,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
@NonNull
|
||||
@Override
|
||||
public PagerAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new PagerAdapter.ViewHolder(ItemRepoRecyclerviewBinding.inflate(getLayoutInflater(), parent, false).getRoot());
|
||||
return new PagerAdapter.ViewHolder(ItemRepoRecyclerviewBinding.inflate(getLayoutInflater(), parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -357,10 +382,11 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
BorderRecyclerView recyclerView;
|
||||
FloatingActionButton btn;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
recyclerView = itemView.findViewById(R.id.recyclerView);
|
||||
public ViewHolder(@NonNull ItemRepoRecyclerviewBinding binding) {
|
||||
super(binding.getRoot());
|
||||
recyclerView = binding.recyclerView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -370,29 +396,35 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
private final List<ModuleUtil.InstalledModule> showList = new ArrayList<>();
|
||||
private final int userId;
|
||||
private final UserHandle userHandle;
|
||||
private final boolean isPick;
|
||||
private boolean isLoaded;
|
||||
private int[] profiles = new int[0];
|
||||
private View.OnClickListener onPickListener;
|
||||
|
||||
private Predicate<ModuleUtil.InstalledModule> customFilter = m -> true;
|
||||
|
||||
ModuleAdapter(int userId, UserHandle userHandle) {
|
||||
this.userId = userId;
|
||||
this.userHandle = userHandle;
|
||||
this(userId, userHandle, false);
|
||||
}
|
||||
|
||||
public void setProfiles(int[] profiles) {
|
||||
this.profiles = profiles;
|
||||
ModuleAdapter(int userId, UserHandle userHandle, boolean isPick) {
|
||||
this.userId = userId;
|
||||
this.userHandle = userHandle;
|
||||
this.isPick = isPick;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_module, parent, false);
|
||||
return new ViewHolder(v);
|
||||
return new ViewHolder(ItemModuleBinding.inflate(getLayoutInflater(), parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
ModuleUtil.InstalledModule item = showList.get(position);
|
||||
holder.root.setAlpha(moduleUtil.isModuleEnabled(item.packageName) ? 1.0f : .5f);
|
||||
String appName;
|
||||
if (item.userId != 0) {
|
||||
appName = String.format("%s (%s)", item.getAppName(), item.userId);
|
||||
|
|
@ -460,7 +492,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
menu.removeItem(R.id.menu_app_info);
|
||||
}
|
||||
if (item.userId == 0) {
|
||||
for (int profile : profiles) {
|
||||
for (int profile : ConfigManager.getUsers()) {
|
||||
if (ModuleUtil.getInstance().getModule(item.packageName, profile) == null) {
|
||||
menu.add(1, profile, 0, getString(R.string.install_to_user, profile));
|
||||
}
|
||||
|
|
@ -468,23 +500,30 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
}
|
||||
});
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(ModulesActivity.this, AppListActivity.class);
|
||||
intent.putExtra("modulePackageName", item.packageName);
|
||||
intent.putExtra("moduleUserId", item.userId);
|
||||
intent.putExtra("userHandle", userHandle);
|
||||
startActivity(intent);
|
||||
});
|
||||
if (!isPick) {
|
||||
holder.root.setAlpha(moduleUtil.isModuleEnabled(item.packageName) ? 1.0f : .5f);
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(ModulesActivity.this, AppListActivity.class);
|
||||
intent.putExtra("modulePackageName", item.packageName);
|
||||
intent.putExtra("moduleUserId", item.userId);
|
||||
intent.putExtra("userHandle", userHandle);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
selectedModule = item;
|
||||
selectedModuleUser = userHandle;
|
||||
return false;
|
||||
});
|
||||
|
||||
holder.appVersion.setVisibility(View.VISIBLE);
|
||||
holder.appVersion.setText(item.versionName);
|
||||
holder.appVersion.setSelected(true);
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
selectedModule = item;
|
||||
selectedModuleUser = userHandle;
|
||||
return false;
|
||||
});
|
||||
holder.appVersion.setVisibility(View.VISIBLE);
|
||||
holder.appVersion.setText(item.versionName);
|
||||
holder.appVersion.setSelected(true);
|
||||
} else {
|
||||
holder.itemView.setTag(item);
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (onPickListener != null) onPickListener.onClick(v);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -503,6 +542,20 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
return new ApplicationFilter();
|
||||
}
|
||||
|
||||
public void setFilter(@NonNull Predicate<ModuleUtil.InstalledModule> filter) {
|
||||
this.customFilter = filter;
|
||||
}
|
||||
|
||||
public void setOnPickListener(View.OnClickListener onPickListener) {
|
||||
this.onPickListener = onPickListener;
|
||||
}
|
||||
|
||||
public List<ModuleUtil.InstalledModule> snapshot() {
|
||||
List<ModuleUtil.InstalledModule> list = new ArrayList<>();
|
||||
list.addAll(searchList);
|
||||
return list;
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
refresh(false);
|
||||
}
|
||||
|
|
@ -515,7 +568,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
private final Runnable reloadModules = new Runnable() {
|
||||
public void run() {
|
||||
searchList.clear();
|
||||
searchList.addAll(moduleUtil.getModules().values().stream().filter(module -> module.userId == userId).collect(Collectors.toList()));
|
||||
searchList.addAll(moduleUtil.getModules().values().stream().filter(module -> module.userId == userId).filter(customFilter).collect(Collectors.toList()));
|
||||
Comparator<PackageInfo> cmp = AppHelper.getAppListComparator(0, pm);
|
||||
searchList.sort((a, b) -> {
|
||||
boolean aChecked = moduleUtil.isModuleEnabled(a.packageName);
|
||||
|
|
@ -539,21 +592,21 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
View root;
|
||||
ConstraintLayout root;
|
||||
ImageView appIcon;
|
||||
TextView appName;
|
||||
TextView appDescription;
|
||||
TextView appVersion;
|
||||
TextView warningText;
|
||||
MaterialCheckBox checkBox;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
root = itemView.findViewById(R.id.item_root);
|
||||
appIcon = itemView.findViewById(R.id.app_icon);
|
||||
appName = itemView.findViewById(R.id.app_name);
|
||||
appDescription = itemView.findViewById(R.id.description);
|
||||
appVersion = itemView.findViewById(R.id.version_name);
|
||||
warningText = itemView.findViewById(R.id.warning);
|
||||
ViewHolder(ItemModuleBinding binding) {
|
||||
super(binding.getRoot());
|
||||
root = binding.itemRoot;
|
||||
appIcon = binding.appIcon;
|
||||
appName = binding.appName;
|
||||
appDescription = binding.description;
|
||||
appVersion = binding.versionName;
|
||||
checkBox = binding.checkbox;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,8 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Filter;
|
||||
import android.widget.TextView;
|
||||
|
|
@ -35,6 +33,7 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
|
@ -42,6 +41,7 @@ import com.google.android.material.snackbar.Snackbar;
|
|||
|
||||
import org.lsposed.manager.ConfigManager;
|
||||
import org.lsposed.manager.R;
|
||||
import org.lsposed.manager.databinding.ItemOnlinemoduleBinding;
|
||||
import org.lsposed.manager.repo.RepoLoader;
|
||||
import org.lsposed.manager.repo.model.OnlineModule;
|
||||
import org.lsposed.manager.ui.activity.base.ListActivity;
|
||||
|
|
@ -148,8 +148,7 @@ public class RepoActivity extends ListActivity implements RepoLoader.Listener {
|
|||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_onlinemodule, parent, false);
|
||||
return new ViewHolder(v);
|
||||
return new ViewHolder(ItemOnlinemoduleBinding.inflate(getLayoutInflater(), parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -211,15 +210,15 @@ public class RepoActivity extends ListActivity implements RepoLoader.Listener {
|
|||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
View root;
|
||||
ConstraintLayout root;
|
||||
TextView appName;
|
||||
TextView appDescription;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
root = itemView.findViewById(R.id.item_root);
|
||||
appName = itemView.findViewById(R.id.app_name);
|
||||
appDescription = itemView.findViewById(R.id.description);
|
||||
ViewHolder(ItemOnlinemoduleBinding binding) {
|
||||
super(binding.getRoot());
|
||||
root = binding.itemRoot;
|
||||
appName = binding.appName;
|
||||
appDescription = binding.description;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import androidx.lifecycle.Lifecycle;
|
|||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.progressindicator.CircularProgressIndicator;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
|
@ -282,9 +283,9 @@ public class RepoItemActivity extends BaseActivity implements RepoLoader.Listene
|
|||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == 0) {
|
||||
return new ViewHolder(ItemRepoReleaseBinding.inflate(getLayoutInflater(), parent, false).getRoot());
|
||||
return new ReleaseViewHolder(ItemRepoReleaseBinding.inflate(getLayoutInflater(), parent, false));
|
||||
} else {
|
||||
return new ViewHolder(ItemRepoLoadmoreBinding.inflate(getLayoutInflater(), parent, false).getRoot());
|
||||
return new LoadmoreViewHolder(ItemRepoLoadmoreBinding.inflate(getLayoutInflater(), parent, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -344,17 +345,30 @@ public class RepoItemActivity extends BaseActivity implements RepoLoader.Listene
|
|||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView title;
|
||||
LinkifyTextView description;
|
||||
View openInBrowser;
|
||||
View viewAssets;
|
||||
MaterialButton openInBrowser;
|
||||
MaterialButton viewAssets;
|
||||
CircularProgressIndicator progress;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
title = view.findViewById(R.id.title);
|
||||
description = view.findViewById(R.id.description);
|
||||
openInBrowser = view.findViewById(R.id.open_in_browser);
|
||||
viewAssets = view.findViewById(R.id.view_assets);
|
||||
progress = view.findViewById(R.id.progress);
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
class ReleaseViewHolder extends ViewHolder {
|
||||
public ReleaseViewHolder(ItemRepoReleaseBinding binding) {
|
||||
super(binding.getRoot());
|
||||
title = binding.title;
|
||||
description = binding.description;
|
||||
openInBrowser = binding.openInBrowser;
|
||||
viewAssets = binding.viewAssets;
|
||||
}
|
||||
}
|
||||
|
||||
class LoadmoreViewHolder extends ViewHolder {
|
||||
public LoadmoreViewHolder(ItemRepoLoadmoreBinding binding) {
|
||||
super(binding.getRoot());
|
||||
title = binding.title;
|
||||
progress = binding.progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -365,9 +379,9 @@ public class RepoItemActivity extends BaseActivity implements RepoLoader.Listene
|
|||
@Override
|
||||
public PagerAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == 0) {
|
||||
return new ViewHolder(ItemRepoReadmeBinding.inflate(getLayoutInflater(), parent, false).getRoot(), viewType);
|
||||
return new ReadmeViewHolder(ItemRepoReadmeBinding.inflate(getLayoutInflater(), parent, false));
|
||||
} else {
|
||||
return new ViewHolder(ItemRepoRecyclerviewBinding.inflate(getLayoutInflater(), parent, false).getRoot(), viewType);
|
||||
return new RecyclerviewBinding(ItemRepoRecyclerviewBinding.inflate(getLayoutInflater(), parent, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -411,14 +425,23 @@ public class RepoItemActivity extends BaseActivity implements RepoLoader.Listene
|
|||
BorderNestedScrollView scrollView;
|
||||
BorderRecyclerView recyclerView;
|
||||
|
||||
public ViewHolder(@NonNull View itemView, int viewType) {
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
if (viewType == 0) {
|
||||
textView = itemView.findViewById(R.id.readme);
|
||||
scrollView = itemView.findViewById(R.id.scrollView);
|
||||
} else {
|
||||
recyclerView = itemView.findViewById(R.id.recyclerView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ReadmeViewHolder extends ViewHolder {
|
||||
public ReadmeViewHolder(ItemRepoReadmeBinding binding) {
|
||||
super(binding.getRoot());
|
||||
textView = binding.readme;
|
||||
scrollView = binding.scrollView;
|
||||
}
|
||||
}
|
||||
|
||||
class RecyclerviewBinding extends ViewHolder {
|
||||
public RecyclerviewBinding(ItemRepoRecyclerviewBinding binding) {
|
||||
super(binding.getRoot());
|
||||
recyclerView = binding.recyclerView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
</vector>
|
||||
|
|
@ -59,4 +59,15 @@
|
|||
android:id="@+id/view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:src="@drawable/ic_baseline_add_24"
|
||||
android:layout_margin="16dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_fitSystemWindowsInsets="bottom"
|
||||
android:contentDescription="@string/add_module_to_user" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
~ Copyright (C) 2020 EdXposed Contributors
|
||||
~ Copyright (C) 2021 LSPosed Contributors
|
||||
-->
|
||||
|
||||
<org.lsposed.manager.ui.widget.EmptyStateRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.lsposed.manager.ui.widget.EmptyStateRecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@
|
|||
<string name="user_title">用户 %d</string>
|
||||
<string name="install_to_user">安装到用户 %d</string>
|
||||
<string name="install_to_user_message">要安装 %1$s 到用户 %2$d 吗?建议手动安装或多开,通过 LSPosed 强制安装可能会出现问题。</string>
|
||||
<string name="module_installed">已安装 %1$s</string>
|
||||
<string name="module_installed">已安装 %1$s 到用户 %2$d</string>
|
||||
<string name="module_install_failed">安装失败</string>
|
||||
|
||||
<!-- AppListActivity -->
|
||||
|
|
|
|||
|
|
@ -85,11 +85,11 @@
|
|||
<string name="module_uninstall_message">Do you want to uninstall this module?</string>
|
||||
<string name="module_uninstalled">Uninstalled %1$s</string>
|
||||
<string name="module_uninstall_failed">Uninstall unsuccessful</string>
|
||||
<string name="module_installed">Added %1$s to user %2$d</string>
|
||||
<string name="module_install_failed">Adding module failed</string>
|
||||
<string name="user_title">User %d</string>
|
||||
<string name="install_to_user">Install to user %d</string>
|
||||
<string name="install_to_user_message">Want to install %1$s to user %2$d? It is recommended to install manually, forcing installation via LSPosed may cause problems.</string>
|
||||
<string name="module_installed">%1$s installed</string>
|
||||
<string name="module_install_failed">install failed</string>
|
||||
|
||||
<!-- AppListActivity -->
|
||||
<string name="compile_speed">Re-optimize</string>
|
||||
|
|
@ -185,4 +185,5 @@
|
|||
<string name="translators"><![CDATA[<a href="https://github.com/LSPosed/LSPosed">LSPosed</a>]]></string>
|
||||
<string name="copy_toast_msg">Copied</string>
|
||||
<string name="list_empty">¯\\\\_(ツ)_\/¯\nNothing here</string>
|
||||
<string name="add_module_to_user">Add module to user</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in New Issue