Skip to content

Commit

Permalink
contents: Implemented Content Manager.
Browse files Browse the repository at this point in the history
  • Loading branch information
longjunyu2 committed Aug 12, 2024
1 parent a5e7095 commit f142d47
Show file tree
Hide file tree
Showing 12 changed files with 447 additions and 32 deletions.
131 changes: 122 additions & 9 deletions app/src/main/java/com/winlator/ContentsFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,30 @@

import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.winlator.contentdialog.ContentDialog;
import com.winlator.contentdialog.ContentInfoDialog;
import com.winlator.contentdialog.ContentUntrustedDialog;
import com.winlator.contents.ContentProfile;
import com.winlator.contents.ContentsManager;
import com.winlator.core.AppUtils;
Expand Down Expand Up @@ -55,22 +62,36 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c

Spinner sContentType = layout.findViewById(R.id.SContentType);
updateContentTypeSpinner(sContentType);
sContentType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
currentContentType = ContentProfile.ContentType.values()[position];
loadContentList();
}

@Override
public void onNothingSelected(AdapterView<?> parent) {

}
});

recyclerView = layout.findViewById(R.id.RecyclerView);
emptyText = layout.findViewById(R.id.TVEmptyText);

View btInstallContent = layout.findViewById(R.id.BTInstallContent);
btInstallContent.setOnClickListener(v -> {
ContentDialog.confirm(getContext(), getString(R.string.do_you_want_to_install_content) + " "
+ getString(R.string.pls_make_sure_content_trustworthy) + " "
+ getString(R.string.content_suffix_is_wcp_packed_xz_zst), () -> {
ContentDialog.confirm(getContext(), getString(R.string.do_you_want_to_install_content) + " " + getString(R.string.pls_make_sure_content_trustworthy) + " " + getString(R.string.content_suffix_is_wcp_packed_xz_zst), () -> {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
getActivity().startActivityFromFragment(this, intent, MainActivity.OPEN_FILE_REQUEST_CODE);
});
});

recyclerView = layout.findViewById(R.id.RecyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
loadContentList();

return layout;
}

Expand Down Expand Up @@ -117,10 +138,11 @@ public void onFailed(ContentsManager.InstallFailedReason reason, Exception e) {
case ERROR_NOPROFILE -> R.string.profile_not_found_in_content;
case ERROR_BADPROFILE -> R.string.profile_cannot_be_recognized;
case ERROR_EXIST -> R.string.content_already_exist;
case ERROR_MISSINGFILES -> R.string.content_is_incomplete;
case ERROR_UNTRUSTPROFILE -> R.string.content_cannot_be_trusted;
default -> R.string.unable_to_install_content;
};
requireActivity().runOnUiThread(() -> ContentDialog.alert(getContext(), getString(R.string.install_failed) + ": "
+ getString(msgId), preloaderDialog::closeOnUiThread));
requireActivity().runOnUiThread(() -> ContentDialog.alert(getContext(), getString(R.string.install_failed) + ": " + getString(msgId), preloaderDialog::closeOnUiThread));
}

@Override
Expand All @@ -132,15 +154,26 @@ public void onSucceed(ContentProfile profile) {
((TextView) dialog.findViewById(R.id.BTConfirm)).setText(R.string._continue);
dialog.setOnConfirmCallback(() -> {
isExtracting = false;
manager.finishInstallContent(profile, callback1);
// TODO
List<ContentProfile.ContentFile> untrustedFiles = manager.getUnTrustedContentFiles(profile);
if (!untrustedFiles.isEmpty()) {
ContentUntrustedDialog untrustedDialog = new ContentUntrustedDialog(getContext(), untrustedFiles);
untrustedDialog.setOnCancelCallback(preloaderDialog::closeOnUiThread);
untrustedDialog.setOnConfirmCallback(() -> manager.finishInstallContent(profile, callback1));
untrustedDialog.show();
} else manager.finishInstallContent(profile, callback1);
});
dialog.setOnCancelCallback(preloaderDialog::closeOnUiThread);
dialog.show();
});

} else {
preloaderDialog.closeOnUiThread();
requireActivity().runOnUiThread(() -> ContentDialog.alert(getContext(), R.string.content_installed_success, null));
requireActivity().runOnUiThread(() -> {
ContentDialog.alert(getContext(), R.string.content_installed_success, null);
manager.syncContents();
currentContentType = profile.type;
loadContentList();
});
}
}
};
Expand All @@ -153,4 +186,84 @@ public void onSucceed(ContentProfile profile) {
}
}
}

private void loadContentList() {
List<ContentProfile> profiles = manager.getProfiles(currentContentType);
if (profiles.isEmpty()) {
emptyText.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
emptyText.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
recyclerView.setAdapter(new ContentItemAdapter(manager.getProfiles(currentContentType)));
}
}

private class ContentItemAdapter extends RecyclerView.Adapter<ContentItemAdapter.ViewHolder> {
private final List<ContentProfile> data;

private static class ViewHolder extends RecyclerView.ViewHolder {
private final ImageView ivIcon;
private final TextView tvVersionName;
private final TextView tvVersionCode;
private final ImageButton ibMenu;

public ViewHolder(@NonNull View view) {
super(view);

ivIcon = view.findViewById(R.id.IVIcon);
tvVersionName = view.findViewById(R.id.TVVersionName);
tvVersionCode = view.findViewById(R.id.TVVersionCode);
ibMenu = view.findViewById(R.id.BTMenu);
}
}

public ContentItemAdapter(List<ContentProfile> data) {
this.data = data;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ContentItemAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.content_list_item, parent, false));
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
final ContentProfile protfile = data.get(position);

int iconId = switch (protfile.type) {
case CONTENT_TYPE_WINE -> R.drawable.icon_wine;
default -> R.drawable.icon_settings;
};
holder.ivIcon.setBackground(getContext().getDrawable(iconId));

holder.tvVersionName.setText(protfile.verName);
holder.tvVersionCode.setText(String.valueOf(protfile.verCode));
holder.ibMenu.setOnClickListener(v -> {
PopupMenu selectionMenu = new PopupMenu(getContext(), holder.ibMenu);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
selectionMenu.setForceShowIcon(true);
selectionMenu.inflate(R.menu.content_popup_menu);
selectionMenu.setOnMenuItemClickListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.content_info) {
new ContentInfoDialog(getContext(), protfile).show();
} else if (itemId == R.id.remove_content) {
ContentDialog.confirm(getContext(), R.string.do_you_want_to_remove_this_content, () -> {
manager.removeContent(protfile);
loadContentList();
});
}
return true;
});
selectionMenu.show();
});
}

@Override
public int getItemCount() {
return data.size();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package com.winlator.contentdialog;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.winlator.R;
import com.winlator.contents.ContentProfile;

import java.util.List;

public class ContentInfoDialog extends ContentDialog {
public ContentInfoDialog(Context context, ContentProfile profile) {
super(context, R.layout.content_info_dialog);
Expand All @@ -16,16 +26,51 @@ public ContentInfoDialog(Context context, ContentProfile profile) {
TextView tvVersion = findViewById(R.id.TVVersion);
TextView tvVersionCode = findViewById(R.id.TVVersionCode);
TextView tvDescription = findViewById(R.id.TVDesc);
TextView tvFiles = findViewById(R.id.TVFiles);
RecyclerView recyclerView = findViewById(R.id.recyclerView);

tvType.setText(profile.type.toString());
tvVersion.setText(profile.verName);
tvVersionCode.setText(String.valueOf(profile.verCode));
tvDescription.setText(profile.desc);
recyclerView.setAdapter(new ContentInfoFileAdapter(profile.fileList));
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));

}

public static class ContentInfoFileAdapter extends RecyclerView.Adapter<ContentInfoFileAdapter.ViewHolder> {
private static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView tvSource;
private final TextView tvtarget;

private ViewHolder(View view) {
super(view);
tvSource = view.findViewById(R.id.TVFileSource);
tvtarget = view.findViewById(R.id.TVFileTarget);
}
}

private final List<ContentProfile.ContentFile> data;

public ContentInfoFileAdapter(List<ContentProfile.ContentFile> data) {
this.data = data;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ContentInfoFileAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.content_file_list_item, parent, false));
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.tvSource.setText(data.get(position).source + " ->");
holder.tvtarget.setText('\t' + data.get(position).target);
}

StringBuilder stb = new StringBuilder();
for (String str : profile.fileList)
stb.append(str).append('\n');
tvFiles.setText(stb.toString());
@Override
public int getItemCount() {
return data.size();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.winlator.contentdialog;

import android.content.Context;
import android.widget.TextView;

import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.winlator.R;
import com.winlator.contents.ContentProfile;

import java.util.List;

public class ContentUntrustedDialog extends ContentDialog {
public ContentUntrustedDialog(Context context, List<ContentProfile.ContentFile> contentFiles) {
super(context, R.layout.content_untrusted_dialog);
setIcon(R.drawable.icon_info);
setTitle(R.string.warning);

RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setAdapter(new ContentInfoDialog.ContentInfoFileAdapter(contentFiles));
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
((TextView) (findViewById(R.id.BTConfirm))).setText(R.string._continue);
}
}
21 changes: 15 additions & 6 deletions app/src/main/java/com/winlator/contents/ContentProfile.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ public class ContentProfile {
public static final String MARK_VERSION_CODE = "versionCode";
public static final String MARK_DESC = "description";
public static final String MARK_FILE_LIST = "files";
public static final String MARK_FILE_SOURCE = "source";
public static final String MARK_FILE_TARGET = "target";

public enum ContentType {
CONTENT_TYPE_WINE ("Wine"),
CONTENT_TYPE_TURNIP ("Turnip"),
CONTENT_TYPE_VIRGL ("VirGL"),
CONTENT_TYPE_DXVK ("DXVK"),
CONTENT_TYPE_VKD3D ("VKD3D");
CONTENT_TYPE_WINE("Wine"),
CONTENT_TYPE_TURNIP("Turnip"),
CONTENT_TYPE_VIRGL("VirGL"),
CONTENT_TYPE_DXVK("DXVK"),
CONTENT_TYPE_VKD3D("VKD3D"),
CONTENT_TYPE_BOX64("Box64");

final String typeName;

ContentType(String typeNmae) {
this.typeName = typeNmae;
}
Expand All @@ -37,9 +41,14 @@ public static ContentType getTypeByName(String name) {
}
}

public static class ContentFile {
public String source;
public String target;
}

public ContentType type;
public String verName;
public int verCode;
public String desc;
public List<String> fileList;
public List<ContentFile> fileList;
}
Loading

0 comments on commit f142d47

Please sign in to comment.