Start implementing new, cleaner Profiles

This commit is contained in:
artdeell 2021-11-30 20:57:48 +03:00
parent 2be5ae2584
commit 4bea845ba4
10 changed files with 344 additions and 7 deletions

View File

@ -37,6 +37,7 @@ import net.kdt.pojavlaunch.fragments.CrashFragment;
import net.kdt.pojavlaunch.fragments.LauncherFragment;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.prefs.screens.LauncherPreferenceFragment;
import net.kdt.pojavlaunch.profiles.ProfileAdapter;
import net.kdt.pojavlaunch.value.MinecraftAccount;
import java.io.File;
@ -198,10 +199,14 @@ public class PojavLauncherActivity extends BaseLauncherActivity
}
//mAvailableVersions;
ArrayAdapter<String> adapterVer = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, mAvailableVersions);
adapterVer.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
mVersionSelector.setAdapter(adapterVer);
if(!LauncherPreferences.PREF_ENABLE_PROFILES) {
ArrayAdapter<String> adapterVer = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, mAvailableVersions);
adapterVer.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
mVersionSelector.setAdapter(adapterVer);
}else{
mVersionSelector.setAdapter(new ProfileAdapter(this));
}
//
statusIsLaunching(false);

View File

@ -12,14 +12,14 @@ import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.F
import androidx.annotation.Keep;
@Keep
@androidx.annotation.Keep
public class ControlDrawerData {
public ArrayList<ControlData> buttonProperties;
public ControlData properties;
public Orientation orientation;
@Keep
@androidx.annotation.Keep
public enum Orientation {
DOWN,
LEFT,

View File

@ -0,0 +1,20 @@
package net.kdt.pojavlaunch.fragments;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import net.kdt.pojavlaunch.R;
public class ProfilesFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.version_profile_editor,container,false);
}
}

View File

@ -34,6 +34,7 @@ public class LauncherPreferences
public static int PREF_CONTROL_BOTTOM_OFFSET = 0;
public static int PREF_CONTROL_LEFT_OFFSET = 0;
public static boolean PREF_SUSTAINED_PERFORMANCE = false;
public static boolean PREF_ENABLE_PROFILES = true;
public static String PREF_GLES_SHRINK_HACK = "0";

View File

@ -0,0 +1,114 @@
package net.kdt.pojavlaunch.profiles;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
import java.util.HashMap;
import java.util.Map;
/*
* Adapter for listing launcher profiles in a Spinner
*/
public class ProfileAdapter extends BaseAdapter {
Map<String, MinecraftProfile> profiles;
Map<String, Bitmap> iconCache;
static final String BASE64_PNG_HEADER = "data:image/png;base64,";
static final MinecraftProfile DUMMY = new MinecraftProfile();
String[] profileArray;
public ProfileAdapter(Context ctx) {
LauncherProfiles.update();
profiles = LauncherProfiles.mainProfileJson.profiles;
profileArray = profiles.keySet().toArray(new String[0]);
iconCache = new HashMap<>();
iconCache.put(null,BitmapFactory.decodeResource(ctx.getResources(),R.drawable.ic_menu_java));
}
/*
* Gets how much profiles are loaded in the adapter right now
* @returns loaded profile count
*/
@Override
public int getCount() {
return profileArray.length;
}
/*
* Gets the profile at a given index
* @param position index to retreive
* @returns MinecraftProfile or null if the index is out of bounds
*/
@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 < profileArray.length && profiles.containsKey(profileArray[position])) {
return profiles.get(profileArray[position]);
}else{
return null;
}
}
/*
* Gets the item ID (crc64 hash of the profile name) for a given index
* @param position index to get the hash for
* @returns ID (crc64 of a profile name string) or -1 if the index is out of bounds
*/
@Override
public long getItemId(int position) {
if(position < profileArray.length) {
return StringCRC64.strhash(profileArray[position]);
}else{
return -1L;
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) v = LayoutInflater.from(parent.getContext()).inflate(R.layout.version_profile_layout,parent,false);
setViewProfile(v,profileArray[position]);
return v;
}
public void setViewProfile(View v, String nm) {
MinecraftProfile prof = profiles.get(nm);
if(prof == null) prof = DUMMY;
Bitmap cachedIcon = iconCache.get(nm);
ImageView iconView = v.findViewById(R.id.vprof_icon_view);
if(cachedIcon == null && prof.icon != null) {
if (prof.icon.startsWith(BASE64_PNG_HEADER)) {
byte[] pngBytes = Base64.decode(prof.icon.substring(BASE64_PNG_HEADER.length()), Base64.DEFAULT);
cachedIcon = BitmapFactory.decodeByteArray(pngBytes,0,pngBytes.length);
}else{
Log.i("IconParser","Unsupported icon: "+prof.icon);
cachedIcon = iconCache.get(null);
}
}
iconView.setImageBitmap(cachedIcon);
if(prof.name != null && !prof.name.isEmpty())
((TextView)v.findViewById(R.id.vprof_profile_name_view)).setText(prof.name);
else
((TextView)v.findViewById(R.id.vprof_profile_name_view)).setText(R.string.unnamed);
TextView tv = v.findViewById(R.id.vprof_version_id_view);
if(prof.lastVersionId != null) switch (prof.lastVersionId) {
case "latest-release":
tv.setText(R.string.profiles_latest_release);
case "latest-snapshot":
tv.setText(R.string.profiles_latest_snapshot);
default:
tv.setText(prof.lastVersionId);
} else tv.setText(android.R.string.unknownName);
}
}

View File

@ -0,0 +1,15 @@
package net.kdt.pojavlaunch.profiles;
import android.content.Context;
import android.view.View;
import android.widget.Spinner;
import android.widget.TextView;
import org.w3c.dom.Text;
public class ProfileEditor {
View mainView;
TextView profileNameView;
Spinner versionSpinner;
Context context;
}

View File

@ -0,0 +1,64 @@
package net.kdt.pojavlaunch.profiles;
import java.nio.charset.StandardCharsets;
public class StringCRC64 {
private final static long POLY = (long) 0xc96c5795d7870f42L; // ECMA-182
private final static long[][] table;
static
{
table = new long[8][256];
for (int n = 0; n < 256; n++)
{
long crc = n;
for (int k = 0; k < 8; k++)
{
if ((crc & 1) == 1)
{
crc = (crc >>> 1) ^ POLY;
}
else
{
crc = (crc >>> 1);
}
}
table[0][n] = crc;
}
for (int n = 0; n < 256; n++)
{
long crc = table[0][n];
for (int k = 1; k < 8; k++)
{
crc = table[0][(int) (crc & 0xff)] ^ (crc >>> 8);
table[k][n] = crc;
}
}
}
public static long strhash(String str) {
byte[] b = str.getBytes(StandardCharsets.US_ASCII);
long value = 0;
int idx = 0;
int len = b.length;
while (len >= 8)
{
value = table[7][(int) (value & 0xff ^ (b[idx] & 0xff))]
^ table[6][(int) ((value >>> 8) & 0xff ^ (b[idx + 1] & 0xff))]
^ table[5][(int) ((value >>> 16) & 0xff ^ (b[idx + 2] & 0xff))]
^ table[4][(int) ((value >>> 24) & 0xff ^ (b[idx + 3] & 0xff))]
^ table[3][(int) ((value >>> 32) & 0xff ^ (b[idx + 4] & 0xff))]
^ table[2][(int) ((value >>> 40) & 0xff ^ (b[idx + 5] & 0xff))]
^ table[1][(int) ((value >>> 48) & 0xff ^ (b[idx + 6] & 0xff))]
^ table[0][(int) ((value >>> 56) ^ b[idx + 7] & 0xff)];
idx += 8;
len -= 8;
}
while (len > 0)
{
value = table[0][(int) ((value ^ b[idx]) & 0xff)] ^ (value >>> 8);
idx++;
len--;
}
return ~value;
}
}

View File

@ -0,0 +1,72 @@
<?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">
<ImageView
android:id="@+id/vprof_editor_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/vprof_editor_toptxv"
app:srcCompat="@drawable/ic_menu_java" />
<TextView
android:id="@+id/vprof_editor_toptxv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/profiles_editing"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/vprof_editor_profile_name_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/profiles_profile_name"
app:layout_constraintBottom_toTopOf="@+id/vprof_editior_profile_name"
app:layout_constraintStart_toStartOf="@+id/vprof_editior_profile_name" />
<EditText
android:id="@+id/vprof_editior_profile_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:hint="@string/unnamed"
android:inputType="textPersonName"
android:minHeight="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/vprof_editor_icon" />
<Spinner
android:id="@+id/spinner2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/vprof_editior_profile_name" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/profiles_profile_version"
app:layout_constraintBottom_toTopOf="@+id/spinner2"
app:layout_constraintStart_toStartOf="@+id/spinner2" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,41 @@
<?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"
android:background="?attr/selectableItemBackground"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/vprof_icon_view"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="4dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_menu_java" />
<TextView
android:id="@+id/vprof_profile_name_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="@android:string/unknownName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/vprof_icon_view"
app:layout_constraintTop_toTopOf="@+id/vprof_icon_view" />
<TextView
android:id="@+id/vprof_version_id_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@android:string/unknownName"
android:textSize="8sp"
app:layout_constraintBottom_toBottomOf="@+id/vprof_icon_view"
app:layout_constraintStart_toStartOf="@+id/vprof_profile_name_view"
app:layout_constraintTop_toBottomOf="@+id/vprof_profile_name_view" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -282,5 +282,10 @@
<string name="gles_hack_none">Don\'t shrink textures</string>
<string name="gles_hack_always">Divides all textures by 2</string>
<string name="gles_hack_sometimes">Divides big textures by /2 or /4</string>
<string name="unnamed">Unnamed</string>
<string name="profiles_latest_snapshot">Latest snapshot</string>
<string name="profiles_latest_release">Latest release</string>
<string name="profiles_editing">Editing profile</string>
<string name="profiles_profile_name">Name</string>
<string name="profiles_profile_version">Version</string>
</resources>