Add UI for OptiFine installation

TBD: actually install OptiFine
This commit is contained in:
BuildTools 2023-06-30 10:33:36 +03:00
parent e731f6e674
commit 3cfaec3b4c
15 changed files with 549 additions and 102 deletions

View File

@ -194,6 +194,8 @@ dependencies {
implementation 'org.tukaani:xz:1.8' implementation 'org.tukaani:xz:1.8'
implementation 'com.github.PojavLauncherTeam:exp4j:60eaec6f78' implementation 'com.github.PojavLauncherTeam:exp4j:60eaec6f78'
implementation 'net.sourceforge.htmlcleaner:htmlcleaner:2.6.1'
// implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.0' // implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.0'
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])

View File

@ -2,15 +2,10 @@ package net.kdt.pojavlaunch.fragments;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ProgressBar;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import net.kdt.pojavlaunch.JavaGUILauncherActivity; import net.kdt.pojavlaunch.JavaGUILauncherActivity;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
@ -18,129 +13,59 @@ import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.modloaders.ForgeDownloadTask; import net.kdt.pojavlaunch.modloaders.ForgeDownloadTask;
import net.kdt.pojavlaunch.modloaders.ForgeUtils; import net.kdt.pojavlaunch.modloaders.ForgeUtils;
import net.kdt.pojavlaunch.modloaders.ForgeVersionListAdapter; import net.kdt.pojavlaunch.modloaders.ForgeVersionListAdapter;
import net.kdt.pojavlaunch.modloaders.ModloaderDownloadListener;
import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy; import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
public class ForgeInstallFragment extends Fragment implements Runnable, View.OnClickListener, ExpandableListView.OnChildClickListener, ModloaderDownloadListener { public class ForgeInstallFragment extends ModVersionListFragment<List<String>> {
public static final String TAG = "ForgeInstallFragment"; public static final String TAG = "ForgeInstallFragment";
private static ModloaderListenerProxy sTaskProxy; private static ModloaderListenerProxy sTaskProxy;
private ExpandableListView mExpandableListView;
private ProgressBar mProgressBar;
private File mDestinationFile;
private LayoutInflater mInflater;
private View mRetryView;
public ForgeInstallFragment() {
super(R.layout.fragment_forge_installer);
}
@Override @Override
public void onAttach(@NonNull Context context) { public void onAttach(@NonNull Context context) {
super.onAttach(context); super.onAttach(context);
this.mInflater = LayoutInflater.from(context);
this.mDestinationFile = new File(Tools.DIR_CACHE, "forge-installer.jar");
} }
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public int getTitleText() {
super.onViewCreated(view, savedInstanceState); return R.string.forge_dl_select_version;
mProgressBar = view.findViewById(R.id.forge_list_progress_bar);
mExpandableListView = view.findViewById(R.id.forge_expandable_version_list);
mExpandableListView.setOnChildClickListener(this);
mRetryView = view.findViewById(R.id.forge_installer_retry_layout);
view.findViewById(R.id.forge_installer_retry_button).setOnClickListener(this);
if(sTaskProxy != null) {
mExpandableListView.setEnabled(false);
sTaskProxy.attachListener(this);
}
new Thread(this).start();
} }
@Override @Override
public void onDestroyView() { public int getNoDataMsg() {
if(sTaskProxy != null) sTaskProxy.detachListener(); return R.string.forge_dl_no_installer;
super.onDestroyView();
} }
@Override @Override
public void run() { public ModloaderListenerProxy getTaskProxy() {
try { return sTaskProxy;
List<String> forgeVersions = ForgeUtils.downloadForgeVersions();
Tools.runOnUiThread(()->{
if(forgeVersions != null) {
mExpandableListView.setAdapter(new ForgeVersionListAdapter(forgeVersions, mInflater));
}else{
mRetryView.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
});
}catch (IOException e) {
Tools.runOnUiThread(()-> {
if (getContext() != null) {
Tools.showError(getContext(), e);
mRetryView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
});
} }
@Override
public void setTaskProxy(ModloaderListenerProxy proxy) {
sTaskProxy = proxy;
} }
@Override @Override
public void onClick(View view) { public List<String> loadVersionList() throws IOException {
mRetryView.setVisibility(View.GONE); return ForgeUtils.downloadForgeVersions();
mProgressBar.setVisibility(View.VISIBLE);
new Thread(this).start();
} }
@Override @Override
public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int i1, long l) { public ExpandableListAdapter createAdapter(List<String> versionList, LayoutInflater layoutInflater) {
String forgeVersion = (String)expandableListView.getExpandableListAdapter().getChild(i, i1); return new ForgeVersionListAdapter(versionList, layoutInflater);
sTaskProxy = new ModloaderListenerProxy();
ForgeDownloadTask downloadTask = new ForgeDownloadTask(sTaskProxy, forgeVersion, mDestinationFile);
sTaskProxy.attachListener(this);
mExpandableListView.setEnabled(false);
new Thread(downloadTask).start();
return true;
} }
@Override @Override
public void onDownloadFinished(File downloadedFile) { public Runnable createDownloadTask(Object selectedVersion, ModloaderListenerProxy listenerProxy) {
Tools.runOnUiThread(()->{ return new ForgeDownloadTask(listenerProxy, (String) selectedVersion, new File(Tools.DIR_CACHE, "forge-installer.jar"));
Context context = requireContext(); }
sTaskProxy.detachListener();
sTaskProxy = null; @Override
mExpandableListView.setEnabled(true); public void onDownloadFinished(Context context, File downloadedFile) {
Intent modInstallerStartIntent = new Intent(context, JavaGUILauncherActivity.class); Intent modInstallerStartIntent = new Intent(context, JavaGUILauncherActivity.class);
ForgeUtils.addAutoInstallArgs(modInstallerStartIntent, downloadedFile, true); ForgeUtils.addAutoInstallArgs(modInstallerStartIntent, downloadedFile, true);
context.startActivity(modInstallerStartIntent); context.startActivity(modInstallerStartIntent);
});
}
@Override
public void onDataNotAvailable() {
Tools.runOnUiThread(()->{
Context context = requireContext();
sTaskProxy.detachListener();
sTaskProxy = null;
mExpandableListView.setEnabled(true);
Tools.dialog(context,
context.getString(R.string.global_error),
context.getString(R.string.forge_dl_no_installer));
});
}
@Override
public void onDownloadError(Exception e) {
Tools.runOnUiThread(()->{
Context context = requireContext();
sTaskProxy.detachListener();
sTaskProxy = null;
mExpandableListView.setEnabled(true);
Tools.showError(context, e);
});
} }
} }

View File

@ -0,0 +1,153 @@
package net.kdt.pojavlaunch.fragments;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.modloaders.ModloaderDownloadListener;
import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy;
import java.io.File;
import java.io.IOException;
public abstract class ModVersionListFragment<T> extends Fragment implements Runnable, View.OnClickListener, ExpandableListView.OnChildClickListener, ModloaderDownloadListener {
public static final String TAG = "ForgeInstallFragment";
//private static ModloaderListenerProxy sTaskProxy;
private ExpandableListView mExpandableListView;
private ProgressBar mProgressBar;
private LayoutInflater mInflater;
private View mRetryView;
public ModVersionListFragment() {
super(R.layout.fragment_mod_version_list);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
this.mInflater = LayoutInflater.from(context);
//this.mDestinationFile = new File(Tools.DIR_CACHE, "forge-installer.jar");
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((TextView)view.findViewById(R.id.title_textview)).setText(getTitleText());
mProgressBar = view.findViewById(R.id.mod_dl_list_progress);
mExpandableListView = view.findViewById(R.id.mod_dl_expandable_version_list);
mExpandableListView.setOnChildClickListener(this);
mRetryView = view.findViewById(R.id.mod_dl_retry_layout);
view.findViewById(R.id.forge_installer_retry_button).setOnClickListener(this);
ModloaderListenerProxy taskProxy = getTaskProxy();
if(taskProxy != null) {
mExpandableListView.setEnabled(false);
taskProxy.attachListener(this);
}
new Thread(this).start();
}
@Override
public void onDestroyView() {
ModloaderListenerProxy taskProxy = getTaskProxy();
if(taskProxy != null) taskProxy.detachListener();
super.onDestroyView();
}
@Override
public void run() {
try {
T versions = loadVersionList();
Tools.runOnUiThread(()->{
if(versions != null) {
mExpandableListView.setAdapter(createAdapter(versions, mInflater));
}else{
mRetryView.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
});
}catch (IOException e) {
Tools.runOnUiThread(()-> {
if (getContext() != null) {
Tools.showError(getContext(), e);
mRetryView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
});
}
}
@Override
public void onClick(View view) {
mRetryView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
new Thread(this).start();
}
@Override
public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int i1, long l) {
Object forgeVersion = expandableListView.getExpandableListAdapter().getChild(i, i1);
ModloaderListenerProxy taskProxy = new ModloaderListenerProxy();
Runnable downloadTask = createDownloadTask(forgeVersion, taskProxy);
//ForgeDownloadTask downloadTask = new ForgeDownloadTask(taskProxy, forgeVersion, mDestinationFile);
setTaskProxy(taskProxy);
taskProxy.attachListener(this);
mExpandableListView.setEnabled(false);
new Thread(downloadTask).start();
return true;
}
@Override
public void onDownloadFinished(File downloadedFile) {
Tools.runOnUiThread(()->{
Context context = requireContext();
getTaskProxy().detachListener();
setTaskProxy(null);
mExpandableListView.setEnabled(true);
onDownloadFinished(context, downloadedFile);
});
}
@Override
public void onDataNotAvailable() {
Tools.runOnUiThread(()->{
Context context = requireContext();
getTaskProxy().detachListener();
setTaskProxy(null);
mExpandableListView.setEnabled(true);
Tools.dialog(context,
context.getString(R.string.global_error),
context.getString(getNoDataMsg()));
});
}
@Override
public void onDownloadError(Exception e) {
Tools.runOnUiThread(()->{
Context context = requireContext();
getTaskProxy().detachListener();
setTaskProxy(null);
mExpandableListView.setEnabled(true);
Tools.showError(context, e);
});
}
public abstract int getTitleText();
public abstract int getNoDataMsg();
public abstract ModloaderListenerProxy getTaskProxy();
public abstract T loadVersionList() throws IOException;
public abstract void setTaskProxy(ModloaderListenerProxy proxy);
public abstract ExpandableListAdapter createAdapter(T versionList, LayoutInflater layoutInflater);
public abstract Runnable createDownloadTask(Object selectedVersion, ModloaderListenerProxy listenerProxy);
public abstract void onDownloadFinished(Context context, File downloadedFile);
}

View File

@ -0,0 +1,60 @@
package net.kdt.pojavlaunch.fragments;
import android.content.Context;
import android.view.LayoutInflater;
import android.widget.ExpandableListAdapter;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy;
import net.kdt.pojavlaunch.modloaders.OptiFineDownloadTask;
import net.kdt.pojavlaunch.modloaders.OptiFineUtils;
import net.kdt.pojavlaunch.modloaders.OptiFineVersionListAdapter;
import java.io.File;
import java.io.IOException;
public class OptiFineInstallFragment extends ModVersionListFragment<OptiFineUtils.OptiFineVersions> {
public static final String TAG = "OptiFineInstallFragment";
private static ModloaderListenerProxy sTaskProxy;
@Override
public int getTitleText() {
return R.string.of_dl_select_version;
}
@Override
public int getNoDataMsg() {
return R.string.of_dl_failed_to_scrape;
}
@Override
public ModloaderListenerProxy getTaskProxy() {
return sTaskProxy;
}
@Override
public OptiFineUtils.OptiFineVersions loadVersionList() throws IOException {
return OptiFineUtils.downloadOptiFineVersions();
}
@Override
public void setTaskProxy(ModloaderListenerProxy proxy) {
sTaskProxy = proxy;
}
@Override
public ExpandableListAdapter createAdapter(OptiFineUtils.OptiFineVersions versionList, LayoutInflater layoutInflater) {
return new OptiFineVersionListAdapter(versionList, layoutInflater);
}
@Override
public Runnable createDownloadTask(Object selectedVersion, ModloaderListenerProxy listenerProxy) {
return new OptiFineDownloadTask((OptiFineUtils.OptiFineVersion) selectedVersion,
new File(Tools.DIR_CACHE, "optifine-installer.jar"), listenerProxy);
}
@Override
public void onDownloadFinished(Context context, File downloadedFile) {
Tools.dialog(context, "Not yet complete", "Installation of OptiFine is not yet implemented. To be done!");
}
}

View File

@ -6,7 +6,6 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools; import net.kdt.pojavlaunch.Tools;
@ -22,6 +21,8 @@ public class ProfileTypeSelectFragment extends Fragment {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.vanilla_profile).setOnClickListener(v -> Tools.swapFragment(requireActivity(), ProfileEditorFragment.class, view.findViewById(R.id.vanilla_profile).setOnClickListener(v -> Tools.swapFragment(requireActivity(), ProfileEditorFragment.class,
ProfileEditorFragment.TAG, false, new Bundle(1))); ProfileEditorFragment.TAG, false, new Bundle(1)));
view.findViewById(R.id.optifine_profile).setOnClickListener(v -> Tools.swapFragment(requireActivity(), OptiFineInstallFragment.class,
OptiFineInstallFragment.TAG, false, null));
view.findViewById(R.id.modded_profile_fabric).setOnClickListener((v)-> view.findViewById(R.id.modded_profile_fabric).setOnClickListener((v)->
Tools.swapFragment(requireActivity(), FabricInstallFragment.class, FabricInstallFragment.TAG, false, null)); Tools.swapFragment(requireActivity(), FabricInstallFragment.class, FabricInstallFragment.TAG, false, null));
view.findViewById(R.id.modded_profile_forge).setOnClickListener((v)-> view.findViewById(R.id.modded_profile_forge).setOnClickListener((v)->

View File

@ -14,7 +14,7 @@ import java.io.IOException;
public class ForgeDownloadTask implements Runnable, Tools.DownloaderFeedback { public class ForgeDownloadTask implements Runnable, Tools.DownloaderFeedback {
private final String mForgeUrl; private final String mForgeUrl;
private final String mForgeVersion; private final String mForgeVersion;
public final File mDestinationFile; private final File mDestinationFile;
private final ModloaderDownloadListener mListener; private final ModloaderDownloadListener mListener;
public ForgeDownloadTask(ModloaderDownloadListener listener, String forgeVersion, File destinationFile) { public ForgeDownloadTask(ModloaderDownloadListener listener, String forgeVersion, File destinationFile) {
this.mListener = listener; this.mListener = listener;

View File

@ -31,6 +31,7 @@ public class ForgeUtils {
return null; return null;
} }
try { try {
//of_test();
return DownloadUtils.downloadStringCached(FORGE_METADATA_URL, "forge_versions", input -> { return DownloadUtils.downloadStringCached(FORGE_METADATA_URL, "forge_versions", input -> {
try { try {
ForgeVersionListHandler handler = new ForgeVersionListHandler(); ForgeVersionListHandler handler = new ForgeVersionListHandler();

View File

@ -0,0 +1,45 @@
package net.kdt.pojavlaunch.modloaders;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.HtmlNode;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.TagNodeVisitor;
import java.io.IOException;
import java.net.URL;
public class OFDownloadPageScraper implements TagNodeVisitor {
public static String run(String urlInput) throws IOException{
return new OFDownloadPageScraper().runInner(urlInput);
}
private String mDownloadFullUrl;
private String runInner(String url) throws IOException {
HtmlCleaner htmlCleaner = new HtmlCleaner();
htmlCleaner.clean(new URL(url)).traverse(this);
return mDownloadFullUrl;
}
@Override
public boolean visit(TagNode parentNode, HtmlNode htmlNode) {
if(isDownloadUrl(parentNode, htmlNode)) {
TagNode tagNode = (TagNode) htmlNode;
String href = tagNode.getAttributeByName("href");
if(!href.startsWith("https://")) href = "https://optifine.net/"+href;
this.mDownloadFullUrl = href;
return false;
}
return true;
}
public boolean isDownloadUrl(TagNode parentNode, HtmlNode htmlNode) {
if(!(htmlNode instanceof TagNode)) return false;
if(parentNode == null) return false;
TagNode tagNode = (TagNode) htmlNode;
if(!(parentNode.getName().equals("span")
&& "Download".equals(parentNode.getAttributeByName("id")))) return false;
return tagNode.getName().equals("a") &&
"onDownload()".equals(tagNode.getAttributeByName("onclick"));
}
}

View File

@ -0,0 +1,53 @@
package net.kdt.pojavlaunch.modloaders;
import com.kdt.mcgui.ProgressLayout;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
import net.kdt.pojavlaunch.utils.DownloadUtils;
import java.io.File;
import java.io.IOException;
public class OptiFineDownloadTask implements Runnable, Tools.DownloaderFeedback{
private final OptiFineUtils.OptiFineVersion mOptiFineVersion;
private final File mDestinationFile;
private final ModloaderDownloadListener mListener;
public OptiFineDownloadTask(OptiFineUtils.OptiFineVersion mOptiFineVersion, File mDestinationFile, ModloaderDownloadListener mListener) {
this.mOptiFineVersion = mOptiFineVersion;
this.mDestinationFile = mDestinationFile;
this.mListener = mListener;
}
@Override
public void run() {
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, 0, R.string.of_dl_progress, mOptiFineVersion.downloadUrl);
try {
if(runCatching()) mListener.onDownloadFinished(mDestinationFile);
}catch (IOException e) {
mListener.onDownloadError(e);
}
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, -1, -1);
}
public boolean runCatching() throws IOException {
String downloadUrl = scrapeDownloadsPage();
if(downloadUrl == null) return false;
DownloadUtils.downloadFileMonitored(downloadUrl, mDestinationFile, new byte[8192], this);
return true;
}
public String scrapeDownloadsPage() throws IOException{
String scrapeResult = OFDownloadPageScraper.run(mOptiFineVersion.downloadUrl);
if(scrapeResult == null) mListener.onDataNotAvailable();
return scrapeResult;
}
@Override
public void updateProgress(int curr, int max) {
int progress100 = (int)(((float)curr / (float)max)*100f);
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, progress100, R.string.of_dl_progress, mOptiFineVersion.versionName);
}
}

View File

@ -0,0 +1,89 @@
package net.kdt.pojavlaunch.modloaders;
import net.kdt.pojavlaunch.utils.DownloadUtils;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import java.util.ArrayList;
import java.util.List;
public class OptiFineScraper implements DownloadUtils.ParseCallback<OptiFineUtils.OptiFineVersions> {
private final OptiFineUtils.OptiFineVersions mOptiFineVersions;
private List<OptiFineUtils.OptiFineVersion> mListInProgress;
private String mMinecraftVersion;
public OptiFineScraper() {
mOptiFineVersions = new OptiFineUtils.OptiFineVersions();
mOptiFineVersions.minecraftVersions = new ArrayList<>();
mOptiFineVersions.optifineVersions = new ArrayList<>();
}
@Override
public OptiFineUtils.OptiFineVersions process(String input) throws DownloadUtils.ParseException {
HtmlCleaner htmlCleaner = new HtmlCleaner();
TagNode tagNode = htmlCleaner.clean(input);
traverseTagNode(tagNode);
insertVersionContent(null);
if(mOptiFineVersions.optifineVersions.size() < 1 ||
mOptiFineVersions.minecraftVersions.size() < 1) throw new DownloadUtils.ParseException(null);
return mOptiFineVersions;
}
public void traverseTagNode(TagNode tagNode) {
if(isDownloadLine(tagNode) && mMinecraftVersion != null) {
traverseDownloadLine(tagNode);
} else if(isMinecraftVersionTag(tagNode)) {
insertVersionContent(tagNode);
} else {
for(TagNode tagNodes : tagNode.getChildTags()) {
traverseTagNode(tagNodes);
}
}
}
private boolean isDownloadLine(TagNode tagNode) {
return tagNode.getName().equals("tr") &&
tagNode.hasAttribute("class") &&
tagNode.getAttributeByName("class").startsWith("downloadLine");
}
private boolean isMinecraftVersionTag(TagNode tagNode) {
return tagNode.getName().equals("h2") &&
tagNode.getText().toString().startsWith("Minecraft ");
}
private void traverseDownloadLine(TagNode tagNode) {
OptiFineUtils.OptiFineVersion optiFineVersion = new OptiFineUtils.OptiFineVersion();
for(TagNode subNode : tagNode.getChildTags()) {
if(!subNode.getName().equals("td")) continue;
switch(subNode.getAttributeByName("class")) {
case "colFile":
optiFineVersion.versionName = subNode.getText().toString();
break;
case "colMirror":
optiFineVersion.downloadUrl = getLinkHref(subNode);
}
}
mListInProgress.add(optiFineVersion);
}
private String getLinkHref(TagNode parent) {
for(TagNode subNode : parent.getChildTags()) {
if(subNode.getName().equals("a") && subNode.hasAttribute("href")) {
return subNode.getAttributeByName("href").replace("http://", "https://");
}
}
return null;
}
private void insertVersionContent(TagNode tagNode) {
if(mListInProgress != null && mMinecraftVersion != null) {
mOptiFineVersions.minecraftVersions.add(mMinecraftVersion);
mOptiFineVersions.optifineVersions.add(mListInProgress);
}
if(tagNode != null) {
mMinecraftVersion = tagNode.getText().toString();
mListInProgress = new ArrayList<>();
}
}
}

View File

@ -0,0 +1,28 @@
package net.kdt.pojavlaunch.modloaders;
import net.kdt.pojavlaunch.utils.DownloadUtils;
import java.io.IOException;
import java.util.List;
public class OptiFineUtils {
public static OptiFineVersions downloadOptiFineVersions() throws IOException {
try {
return DownloadUtils.downloadStringCached("https://optifine.net/downloads",
"of_downloads_page", new OptiFineScraper());
}catch (DownloadUtils.ParseException e) {
e.printStackTrace();
return null;
}
}
public static class OptiFineVersions {
public List<String> minecraftVersions;
public List<List<OptiFineVersion>> optifineVersions;
}
public static class OptiFineVersion {
public String versionName;
public String downloadUrl;
}
}

View File

@ -0,0 +1,77 @@
package net.kdt.pojavlaunch.modloaders;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.TextView;
public class OptiFineVersionListAdapter extends BaseExpandableListAdapter implements ExpandableListAdapter {
private final OptiFineUtils.OptiFineVersions mOptiFineVersions;
private final LayoutInflater mLayoutInflater;
public OptiFineVersionListAdapter(OptiFineUtils.OptiFineVersions optiFineVersions, LayoutInflater mLayoutInflater) {
mOptiFineVersions = optiFineVersions;
this.mLayoutInflater = mLayoutInflater;
}
@Override
public int getGroupCount() {
return mOptiFineVersions.minecraftVersions.size();
}
@Override
public int getChildrenCount(int i) {
return mOptiFineVersions.optifineVersions.get(i).size();
}
@Override
public Object getGroup(int i) {
return mOptiFineVersions.minecraftVersions.get(i);
}
@Override
public Object getChild(int i, int i1) {
return mOptiFineVersions.optifineVersions.get(i).get(i1);
}
@Override
public long getGroupId(int i) {
return i;
}
@Override
public long getChildId(int i, int i1) {
return i1;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(int i, boolean b, View convertView, ViewGroup viewGroup) {
if(convertView == null)
convertView = mLayoutInflater.inflate(android.R.layout.simple_expandable_list_item_1, viewGroup, false);
((TextView) convertView).setText((String)getGroup(i));
return convertView;
}
@Override
public View getChildView(int i, int i1, boolean b, View convertView, ViewGroup viewGroup) {
if(convertView == null)
convertView = mLayoutInflater.inflate(android.R.layout.simple_expandable_list_item_1, viewGroup, false);
((TextView) convertView).setText(((OptiFineUtils.OptiFineVersion)getChild(i,i1)).versionName);
return convertView;
}
@Override
public boolean isChildSelectable(int i, int i1) {
return true;
}
}

View File

@ -36,7 +36,7 @@
<ExpandableListView <ExpandableListView
android:scrollbarThumbVertical="@color/minebutton_color" android:scrollbarThumbVertical="@color/minebutton_color"
android:id="@+id/forge_expandable_version_list" android:id="@+id/mod_dl_expandable_version_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1"> android:layout_weight="1">
@ -44,7 +44,7 @@
</ExpandableListView> </ExpandableListView>
<LinearLayout <LinearLayout
android:id="@+id/forge_installer_retry_layout" android:id="@+id/mod_dl_retry_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
@ -70,7 +70,7 @@
</LinearLayout> </LinearLayout>
<ProgressBar <ProgressBar
android:id="@+id/forge_list_progress_bar" android:id="@+id/mod_dl_list_progress"
style="@style/Widget.AppCompat.ProgressBar.Horizontal" style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -49,6 +49,15 @@
android:layout_marginTop="@dimen/padding_large" android:layout_marginTop="@dimen/padding_large"
app:layout_constraintTop_toBottomOf="@+id/view" /> app:layout_constraintTop_toBottomOf="@+id/view" />
<com.kdt.mcgui.MineButton
android:id="@+id/optifine_profile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/padding_large"
android:text="@string/create_profile_optifine"
android:layout_marginTop="@dimen/padding_large"
app:layout_constraintTop_toBottomOf="@+id/view" />
<!-- Modded versions --> <!-- Modded versions -->

View File

@ -391,4 +391,8 @@
<string name="create_profile_vanilla_like_versions">Vanilla-like versions</string> <string name="create_profile_vanilla_like_versions">Vanilla-like versions</string>
<string name="create_profile_modded_versions">Modded versions</string> <string name="create_profile_modded_versions">Modded versions</string>
<string name="fabric_dl_loader_title">Select versions</string> <string name="fabric_dl_loader_title">Select versions</string>
<string name="of_dl_select_version">Select OptiFine version</string>
<string name="of_dl_failed_to_scrape">Failed to get the OptiFine download link</string>
<string name="of_dl_progress">Downloading %s</string>
<string name="create_profile_optifine">Create OptiFine profile</string>
</resources> </resources>