Addec "Create modded profile" button and moved fabric/forge installation under it

Also:
 - Not layouts are more standardized
This commit is contained in:
BuildTools 2023-06-28 14:26:12 +03:00
parent d5935be9aa
commit 85b3a42dd3
11 changed files with 165 additions and 81 deletions

View File

@ -1,7 +1,6 @@
package com.kdt.mcgui;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static net.kdt.pojavlaunch.fragments.ProfileEditorFragment.DELETED_PROFILE;
import android.annotation.SuppressLint;
@ -9,6 +8,7 @@ import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.transition.Slide;
import android.transition.Transition;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
@ -19,15 +19,18 @@ import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import androidx.fragment.app.FragmentActivity;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.extra.ExtraConstants;
import net.kdt.pojavlaunch.extra.ExtraCore;
import net.kdt.pojavlaunch.fragments.ModdedProfileSelectFragment;
import net.kdt.pojavlaunch.fragments.ProfileEditorFragment;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.profiles.ProfileAdapter;
import net.kdt.pojavlaunch.fragments.ProfileEditorFragment;
import net.kdt.pojavlaunch.profiles.ProfileAdapterExtra;
import fr.spse.extended_view.ExtendedTextView;
@ -36,6 +39,8 @@ import fr.spse.extended_view.ExtendedTextView;
* dropdown popup view with a custom direction.
*/
public class mcVersionSpinner extends ExtendedTextView {
private static final int VERSION_SPINNER_PROFILE_CREATE = 0;
private static final int VERSION_SPINNER_PROFILE_CREATE_MODDED = 1;
public mcVersionSpinner(@NonNull Context context) {
super(context);
init();
@ -52,8 +57,15 @@ public class mcVersionSpinner extends ExtendedTextView {
/* The class is in charge of displaying its own list with adapter content being known in advance */
private ListView mListView = null;
private PopupWindow mPopupWindow = null;
private final ProfileAdapter mProfileAdapter = new ProfileAdapter(getContext(), true);
private int mSelectedProfilePosition;
private Object mPopupAnimation;
private final ProfileAdapter mProfileAdapter = new ProfileAdapter(getContext(), new ProfileAdapterExtra[]{
new ProfileAdapterExtra(VERSION_SPINNER_PROFILE_CREATE,
R.string.create_profile,
ResourcesCompat.getDrawable(getResources(), R.drawable.ic_add, null)),
new ProfileAdapterExtra(VERSION_SPINNER_PROFILE_CREATE_MODDED,
R.string.create_profile_modded,
ResourcesCompat.getDrawable(getResources(), R.drawable.ic_add_modded, null))
});
/** Set the selection AND saves it as a shared preference */
@ -63,11 +75,9 @@ public class mcVersionSpinner extends ExtendedTextView {
.putString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE,
mProfileAdapter.getItem(position).toString())
.apply();
if(mPopupWindow != null) mPopupWindow.dismiss();
}
public void setSelection(int position){
mSelectedProfilePosition = position;
if(mListView != null) mListView.setSelection(position);
mProfileAdapter.setViewProfile(this, (String) mProfileAdapter.getItem(position), false);
}
@ -115,13 +125,24 @@ public class mcVersionSpinner extends ExtendedTextView {
mListView = (ListView) inflate(getContext(), R.layout.spinner_mc_version, null);
mListView.setAdapter(mProfileAdapter);
mListView.setOnItemClickListener((parent, view, position, id) -> {
if(position == mProfileAdapter.getCount() - 1){
mPopupWindow.dismiss();
Tools.swapFragment((FragmentActivity) getContext(), ProfileEditorFragment.class,
ProfileEditorFragment.TAG, true, new Bundle(1));
return;
Object item = mProfileAdapter.getItem(position);
if(item instanceof String) {
hidePopup(true);
setProfileSelection(position);
}else if(item instanceof ProfileAdapterExtra) {
hidePopup(false);
ProfileAdapterExtra extra = (ProfileAdapterExtra) item;
switch (extra.id) {
case VERSION_SPINNER_PROFILE_CREATE:
Tools.swapFragment((FragmentActivity) getContext(), ProfileEditorFragment.class,
ProfileEditorFragment.TAG, true, new Bundle(1));
break;
case VERSION_SPINNER_PROFILE_CREATE_MODDED:
Tools.swapFragment((FragmentActivity) getContext(), ModdedProfileSelectFragment.class,
ModdedProfileSelectFragment.TAG, true, null);
break;
}
}
setProfileSelection(position);
});
mPopupWindow = new PopupWindow(mListView, MATCH_PARENT, getContext().getResources().getDimensionPixelOffset(R.dimen._184sdp));
@ -142,14 +163,26 @@ public class mcVersionSpinner extends ExtendedTextView {
// Custom animation, nice slide in
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
Slide transition = new Slide(Gravity.BOTTOM);
mPopupWindow.setEnterTransition(transition);
mPopupWindow.setExitTransition(transition);
mPopupAnimation = new Slide(Gravity.BOTTOM);
mPopupWindow.setEnterTransition((Transition) mPopupAnimation);
mPopupWindow.setExitTransition((Transition) mPopupAnimation);
}
}
private void hidePopup(boolean animate) {
if(mPopupWindow == null) return;
if(!animate && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mPopupWindow.setEnterTransition(null);
mPopupWindow.setExitTransition(null);
mPopupWindow.dismiss();
mPopupWindow.setEnterTransition((Transition) mPopupAnimation);
mPopupWindow.setExitTransition((Transition) mPopupAnimation);
}else {
mPopupWindow.dismiss();
}
}
public ProfileAdapter getProfileAdapter() {
return mProfileAdapter;
}
}

View File

@ -0,0 +1,27 @@
package net.kdt.pojavlaunch.fragments;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
public class ModdedProfileSelectFragment extends Fragment {
public static final String TAG = "ModdedProfileSelectFragment";
public ModdedProfileSelectFragment() {
super(R.layout.fragment_mod_profile);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.modded_profile_fabric).setOnClickListener((v)->
Tools.swapFragment(requireActivity(), FabricInstallFragment.class, FabricInstallFragment.TAG, false, null));
view.findViewById(R.id.modded_profile_forge).setOnClickListener((v)->
Tools.swapFragment(requireActivity(), ForgeInstallFragment.class, ForgeInstallFragment.TAG, false, null));
}
}

View File

@ -1,7 +1,5 @@
package net.kdt.pojavlaunch.fragments;
import static net.kdt.pojavlaunch.profiles.ProfileAdapter.CREATE_PROFILE_MAGIC;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
@ -157,7 +155,7 @@ public class ProfileEditorFragment extends Fragment {
private MinecraftProfile getProfile(@NonNull String profile){
MinecraftProfile minecraftProfile;
if(getArguments() == null && !profile.equals(CREATE_PROFILE_MAGIC)) {
if(getArguments() == null) {
minecraftProfile = new MinecraftProfile(LauncherProfiles.mainProfileJson.profiles.get(profile));
mProfileKey = profile;
}else{

View File

@ -29,25 +29,17 @@ import fr.spse.extended_view.ExtendedTextView;
*/
public class ProfileAdapter extends BaseAdapter {
private Map<String, MinecraftProfile> mProfiles;
public static final String CREATE_PROFILE_MAGIC = "___extra____profile-create";
private final MinecraftProfile dummy = new MinecraftProfile();
private MinecraftProfile mCreateProfile;
private List<String> mProfileList;
private final ProfileAdapterExtra[] mExtraEntires;
public ProfileAdapter(Context context, boolean enableCreateButton) {
public ProfileAdapter(Context context, ProfileAdapterExtra[] extraEntries) {
ProfileIconCache.initDefault(context);
LauncherProfiles.update();
mProfiles = new HashMap<>(LauncherProfiles.mainProfileJson.profiles);
if(enableCreateButton) {
mCreateProfile = new MinecraftProfile();
mCreateProfile.name = context.getString(R.string.create_profile);
mCreateProfile.lastVersionId = null;
}
if(extraEntries == null) mExtraEntires = new ProfileAdapterExtra[0];
else mExtraEntires = extraEntries;
mProfileList = new ArrayList<>(Arrays.asList(mProfiles.keySet().toArray(new String[0])));
if(enableCreateButton) {
mProfileList.add(ProfileAdapter.CREATE_PROFILE_MAGIC);
mProfiles.put(CREATE_PROFILE_MAGIC, mCreateProfile);
}
}
/*
* Gets how much profiles are loaded in the adapter right now
@ -55,7 +47,7 @@ public class ProfileAdapter extends BaseAdapter {
*/
@Override
public int getCount() {
return mProfileList.size();
return mProfileList.size() + mExtraEntires.length;
}
/*
* Gets the profile at a given index
@ -64,12 +56,15 @@ public class ProfileAdapter extends BaseAdapter {
*/
@Override
public Object getItem(int position) {
//safe since the second check in the and statement will be skipped if the first one fails
if(position < mProfileList.size() && mProfiles.containsKey(mProfileList.get(position))) {
return mProfileList.get(position);
}else{
return null;
int profileListSize = mProfileList.size();
int extraPosition = position - profileListSize;
if(position < profileListSize){
String profileName = mProfileList.get(position);
if(mProfiles.containsKey(profileName)) return profileName;
}else if(extraPosition >= 0 && extraPosition < mExtraEntires.length) {
return mExtraEntires[extraPosition];
}
return null;
}
public int resolveProfileIndex(String name) {
@ -85,8 +80,6 @@ public class ProfileAdapter extends BaseAdapter {
public void notifyDataSetChanged() {
mProfiles = new HashMap<>(LauncherProfiles.mainProfileJson.profiles);
mProfileList = new ArrayList<>(Arrays.asList(mProfiles.keySet().toArray(new String[0])));
mProfileList.add(ProfileAdapter.CREATE_PROFILE_MAGIC);
mProfiles.put(CREATE_PROFILE_MAGIC, mCreateProfile);
super.notifyDataSetChanged();
}
@ -94,7 +87,9 @@ public class ProfileAdapter extends BaseAdapter {
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_version_profile_layout,parent,false);
setViewProfile(v,mProfileList.get(position), true);
Object profileObject = getItem(position);
if(profileObject instanceof String) setViewProfile(v, (String) profileObject, true);
else if(profileObject instanceof ProfileAdapterExtra) setViewExtra(v, (ProfileAdapterExtra) profileObject);
return v;
}
@ -131,7 +126,12 @@ public class ProfileAdapter extends BaseAdapter {
String selectedProfile = LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE,"");
extendedTextView.setBackgroundColor(selectedProfile.equals(nm) ? ColorUtils.setAlphaComponent(Color.WHITE,60) : Color.TRANSPARENT);
}else extendedTextView.setBackgroundColor(Color.TRANSPARENT);
}
public void setViewExtra(View v, ProfileAdapterExtra extra) {
ExtendedTextView extendedTextView = (ExtendedTextView) v;
extendedTextView.setCompoundDrawablesRelative(extra.icon, null, extendedTextView.getCompoundsDrawables()[2], null);
extendedTextView.setText(extra.name);
extendedTextView.setBackgroundColor(Color.TRANSPARENT);
}
}

View File

@ -0,0 +1,15 @@
package net.kdt.pojavlaunch.profiles;
import android.graphics.drawable.Drawable;
public class ProfileAdapterExtra {
public final int id;
public final int name;
public final Drawable icon;
public ProfileAdapterExtra(int id, int name, Drawable icon) {
this.id = id;
this.name = name;
this.icon = icon;
}
}

View File

@ -1,7 +1,5 @@
package net.kdt.pojavlaunch.profiles;
import static net.kdt.pojavlaunch.profiles.ProfileAdapter.CREATE_PROFILE_MAGIC;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
@ -46,21 +44,11 @@ public class ProfileIconCache {
icon = ProfileIconCache.submitIcon(resources, profileName, b64Icon.substring(BASE64_PNG_HEADER.length()));
}else{
Log.i("IconParser","Unsupported icon: "+b64Icon);
if(profileName.equals(CREATE_PROFILE_MAGIC)){
icon = ProfileIconCache.pushAddProfileIcon(ResourcesCompat.getDrawable(resources, R.drawable.ic_add, null));
}else{
icon = ProfileIconCache.pushDefaultIcon(profileName);
}
icon = ProfileIconCache.pushDefaultIcon(profileName);
}
return icon;
}
public static Drawable pushAddProfileIcon(Drawable drawable){
sIconCache.put(CREATE_PROFILE_MAGIC, drawable);
return drawable;
}
public static Drawable pushDefaultIcon(String key) {
sIconCache.put(key, sDefaultIcon);

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

View File

@ -1,35 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_app">
android:background="@color/background_app"
android:paddingHorizontal="@dimen/fragment_padding_medium">
<TextView
android:id="@+id/fabric_installer_label_loader_ver"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="@string/fabric_dl_loader_version"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@+id/fabric_installer_loader_ver_spinner"
app:layout_constraintStart_toStartOf="@+id/fabric_installer_loader_ver_spinner"
app:layout_constraintTop_toTopOf="parent" />
<Spinner
android:id="@+id/fabric_installer_loader_ver_spinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:minHeight="48dp"
android:background="@drawable/background_line"
android:minHeight="48dp"
android:paddingVertical="0dp"
android:paddingStart="7dp"
android:paddingEnd="7dp"
android:layout_marginTop="@dimen/_24sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fabric_installer_label_loader_ver" />
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="wrap_content"
@ -45,12 +45,12 @@
android:id="@+id/fabric_installer_retry_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal"
android:paddingTop="@dimen/fragment_padding_medium"
android:paddingBottom="@dimen/fragment_padding_medium"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/fabric_installer_loader_ver_spinner">
app:layout_constraintTop_toBottomOf="@+id/fabric_installer_loader_ver_spinner"
tools:layout_editor_absoluteX="13dp">
<TextView
android:layout_width="0dp"
@ -58,7 +58,7 @@
android:layout_marginStart="10dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="@string/forge_dl_failed_to_load_list"
android:text="@string/modloader_dl_failed_to_load_list"
android:textColor="#FFFF0000"
android:textStyle="bold" />
@ -73,31 +73,27 @@
android:id="@+id/fabric_installer_game_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="@string/fabric_dl_game_version"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fabric_installer_retry_layout" />
app:layout_constraintBottom_toTopOf="@+id/fabric_installer_version_select_label"
app:layout_constraintStart_toStartOf="@+id/fabric_installer_version_select_label" />
<TextView
android:id="@+id/fabric_installer_version_select_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_weight="1"
android:layout_marginTop="@dimen/_24sdp"
android:background="@drawable/background_line"
android:hint="@string/version_select_hint"
android:paddingHorizontal="@dimen/_12sdp"
app:layout_constraintEnd_toStartOf="@+id/fabric_installer_game_version_change"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fabric_installer_game_version" />
app:layout_constraintTop_toBottomOf="@+id/fabric_installer_retry_layout" />
<Button
android:id="@+id/fabric_installer_game_version_change"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:text="@string/global_select"
app:layout_constraintBottom_toBottomOf="@+id/fabric_installer_version_select_label"
app:layout_constraintEnd_toEndOf="parent"
@ -107,9 +103,7 @@
android:id="@+id/fabric_installer_start_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:enabled="false"
android:text="@string/fabric_dl_install"
@ -124,8 +118,6 @@
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:indeterminate="true"
android:visibility="visible"

View File

@ -3,7 +3,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/background_app">
android:background="@color/background_app"
android:paddingHorizontal="@dimen/fragment_padding_medium">
<TextView
android:layout_width="match_parent"
@ -38,7 +39,7 @@
android:layout_marginStart="10dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="@string/forge_dl_failed_to_load_list"
android:text="@string/modloader_dl_failed_to_load_list"
android:textColor="#FFFF0000"
android:textStyle="bold" />

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_app"
android:paddingHorizontal="@dimen/fragment_padding_medium"
android:orientation="vertical">
<com.kdt.mcgui.MineButton
android:id="@+id/modded_profile_fabric"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/modloader_dl_install_fabric" />
<com.kdt.mcgui.MineButton
android:id="@+id/modded_profile_forge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/modloader_dl_install_forge" />
</LinearLayout>

View File

@ -375,7 +375,7 @@
<string name="preference_force_big_core_desc">Forces the Minecraft render thread to run on the core with the highest max frequency</string>
<string name="version_select_hint">Select a version</string>
<string name="forge_dl_progress">Downloading installer for %s</string>
<string name="forge_dl_failed_to_load_list">Failed to load the version list!</string>
<string name="modloader_dl_failed_to_load_list">Failed to load the version list!</string>
<string name="forge_dl_no_installer">Sorry, but this version of Forge does not have an installer, which is not yet supported.</string>
<string name="forge_dl_select_version">Select Forge version</string>
<string name="fabric_dl_progress">Downloading Fabric installer</string>
@ -383,4 +383,7 @@
<string name="fabric_dl_game_version">Minecraft version</string>
<string name="fabric_dl_install">Install</string>
<string name="fabric_dl_cant_read_meta">Failed to read Fabric metadata. Please try again later.</string>
<string name="modloader_dl_install_fabric">Create Fabric profile</string>
<string name="modloader_dl_install_forge">Create Forge profile</string>
<string name="create_profile_modded">Create modded profile</string>
</resources>