Merge pull request #16 from alexytomi/qol-betterLocalandDemoMessages

Merge alexytomi's changes for
1. Disallow creation of local accounts when no Microsoft account with game ownership is logged in
2. Disallow creation of local accounts when only a Microsoft account that lacks game ownership/demo mode is logged in
3. Prevent playing versions before 1.3.1 when no Microsoft account with game ownership is logged in, including demo accounts. (Demo mode does not exist before 1.3.1)
This commit is contained in:
Stella 2025-06-21 00:03:13 -06:00 committed by GitHub
commit 66db228605
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 96 additions and 21 deletions

View File

@ -1,6 +1,8 @@
package net.kdt.pojavlaunch;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static net.kdt.pojavlaunch.Tools.hasNoOnlineProfileDialog;
import android.Manifest;
import android.app.NotificationManager;
import android.content.Context;
@ -139,7 +141,7 @@ public class LauncherActivity extends BaseActivity {
}
if (isOlderThan13) {
Toast.makeText(this, R.string.toast_not_available_demo, Toast.LENGTH_LONG).show();
hasNoOnlineProfileDialog(this, getString(R.string.global_error), getString(R.string.demo_versions_supported));
return false;
}
}

View File

@ -8,6 +8,13 @@ import androidx.annotation.Nullable;
import net.kdt.pojavlaunch.value.MinecraftAccount;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class PojavProfile {
private static final String PROFILE_PREF = "pojav_profile";
private static final String PROFILE_PREF_FILE = "file";
@ -29,6 +36,25 @@ public class PojavProfile {
}
return name;
}
public static List<MinecraftAccount> getAllProfiles(){
List<MinecraftAccount> mcAccountList = new ArrayList<>();;
for (String accountName : getAllProfilesList()){
mcAccountList.add(MinecraftAccount.load(accountName));
}
return mcAccountList;
}
public static List<String> getAllProfilesList(){
List<String> accountList = new ArrayList<>();
File accountFolder = new File(Tools.DIR_ACCOUNT_NEW);
if(accountFolder.exists() && accountFolder.list() != null){
for (String fileName : Objects.requireNonNull(accountFolder.list())) {
accountList.add(fileName.substring(0, fileName.length() - 5));
}
}
return accountList;
}
public static void setCurrentProfile(@NonNull Context ctx, @Nullable Object obj) {
SharedPreferences.Editor pref = getPrefs(ctx).edit();

View File

@ -3,6 +3,7 @@ package net.kdt.pojavlaunch;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.P;
import static net.kdt.pojavlaunch.PojavApplication.sExecutorService;
import static net.kdt.pojavlaunch.PojavProfile.getAllProfiles;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_IGNORE_NOTCH;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE;
@ -1452,4 +1453,37 @@ public final class Tools {
MinecraftAccount currentProfile = PojavProfile.getCurrentProfileContent(ctx, null);
return currentProfile == null || currentProfile.isLocal();
}
public static boolean hasOnlineProfile(){
for (MinecraftAccount accountToCheck : getAllProfiles()) {
if (!accountToCheck.isLocal() && !accountToCheck.isDemo()) {
return true;
}
}
return false;
}
public static void hasNoOnlineProfileDialog(Activity activity, @Nullable Runnable run, @Nullable String customTitle, @Nullable String customMessage){
if (hasOnlineProfile() && !Tools.isDemoProfile(activity)){
if (run != null) { // Demo profile handling should be using customTitle and customMessage
run.run();
}
} else { // If there is no online profile, show a dialog
customTitle = customTitle == null ? activity.getString(R.string.no_minecraft_account_found) : customTitle;
customMessage = customMessage == null ? activity.getString(R.string.feature_requires_java_account) : customMessage;
dialogOnUiThread(activity, customTitle, customMessage);
}
}
// Some boilerplate to reduce boilerplate elsewhere
public static void hasNoOnlineProfileDialog(Activity activity){
hasNoOnlineProfileDialog(activity, null, null, null);
}
public static void hasNoOnlineProfileDialog(Activity activity, Runnable run){
hasNoOnlineProfileDialog(activity, run, null, null);
}
public static void hasNoOnlineProfileDialog(Activity activity, String customTitle, String customMessage){
hasNoOnlineProfileDialog(activity, null, customTitle, customMessage);
}
}

View File

@ -1,5 +1,7 @@
package net.kdt.pojavlaunch.fragments;
import static net.kdt.pojavlaunch.Tools.hasOnlineProfile;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
@ -31,6 +33,10 @@ public class LocalLoginFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
// This is overkill but meh
if (!hasOnlineProfile()){
Tools.swapFragment(requireActivity(), MainMenuFragment.class, MainMenuFragment.TAG, null);
}
mUsernameEditText = view.findViewById(R.id.login_edit_email);
view.findViewById(R.id.login_button).setOnClickListener(v -> {
if(!checkEditText()) {

View File

@ -1,5 +1,7 @@
package net.kdt.pojavlaunch.fragments;
import static net.kdt.pojavlaunch.Tools.hasNoOnlineProfileDialog;
import static net.kdt.pojavlaunch.Tools.hasOnlineProfile;
import static net.kdt.pojavlaunch.Tools.openPath;
import static net.kdt.pojavlaunch.Tools.shareLog;
@ -53,11 +55,13 @@ public class MainMenuFragment extends Fragment {
mNewsButton.setOnClickListener(v -> Tools.openURL(requireActivity(), Tools.URL_HOME));
mDiscordButton.setOnClickListener(v -> Tools.openURL(requireActivity(), getString(R.string.discord_invite)));
mCustomControlButton.setOnClickListener(v -> startActivity(new Intent(requireContext(), CustomControlsActivity.class)));
mInstallJarButton.setOnClickListener(v -> runInstallerWithConfirmation(false));
mInstallJarButton.setOnLongClickListener(v->{
runInstallerWithConfirmation(true);
return true;
});
if (hasOnlineProfile()) {
mInstallJarButton.setOnClickListener(v -> runInstallerWithConfirmation(false));
mInstallJarButton.setOnLongClickListener(v -> {
runInstallerWithConfirmation(true);
return true;
});
} else mInstallJarButton.setOnClickListener(v -> hasNoOnlineProfileDialog(requireActivity()));
mEditProfileButton.setOnClickListener(v -> mVersionSpinner.openProfileEditor(requireActivity()));
mPlayButton.setOnClickListener(v -> ExtraCore.setValue(ExtraConstants.LAUNCH_GAME, true));
@ -65,13 +69,12 @@ public class MainMenuFragment extends Fragment {
mShareLogsButton.setOnClickListener((v) -> shareLog(requireContext()));
mOpenDirectoryButton.setOnClickListener((v)-> {
Tools.switchDemo(Tools.isDemoProfile(v.getContext())); // avoid switching accounts being able to access
if(Tools.isDemoProfile(v.getContext())){
Toast.makeText(v.getContext(), R.string.toast_not_available_demo, Toast.LENGTH_LONG).show();
return;
}
if (Tools.isDemoProfile(v.getContext())){ // Say a different message when on demo profile since they might see the hidden demo folder
hasNoOnlineProfileDialog(getActivity(), getString(R.string.demo_unsupported), getString(R.string.change_account));
} else if (!hasOnlineProfile()) { // Otherwise display the generic pop-up to log in
hasNoOnlineProfileDialog(requireActivity());
} else openPath(v.getContext(), getCurrentProfileDirectory(), false);
openPath(v.getContext(), getCurrentProfileDirectory(), false);
});
@ -97,12 +100,6 @@ public class MainMenuFragment extends Fragment {
}
private void runInstallerWithConfirmation(boolean isCustomArgs) {
// avoid using custom installers to install a version
if(Tools.isLocalProfile(requireContext()) || Tools.isDemoProfile(requireContext())){
Toast.makeText(requireContext(), R.string.toast_not_available_demo, Toast.LENGTH_LONG).show();
return;
}
if (ProgressKeeper.getTaskCount() == 0)
Tools.installMod(requireActivity(), isCustomArgs);
else

View File

@ -1,5 +1,8 @@
package net.kdt.pojavlaunch.fragments;
import static net.kdt.pojavlaunch.Tools.hasNoOnlineProfileDialog;
import static net.kdt.pojavlaunch.Tools.hasOnlineProfile;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
@ -42,8 +45,8 @@ public class ProfileTypeSelectFragment extends Fragment {
}
private void tryInstall(Class<? extends Fragment> fragmentClass, String tag){
if(Tools.isLocalProfile(requireContext()) || Tools.isDemoProfile(requireContext())){
Toast.makeText(requireContext(), R.string.toast_not_available_demo, Toast.LENGTH_LONG).show();
if(!hasOnlineProfile()){
hasNoOnlineProfileDialog(requireActivity());
} else {
Tools.swapFragment(requireActivity(), fragmentClass, tag, null);
}

View File

@ -1,5 +1,7 @@
package net.kdt.pojavlaunch.fragments;
import static net.kdt.pojavlaunch.Tools.hasNoOnlineProfileDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
@ -24,6 +26,6 @@ public class SelectAuthFragment extends Fragment {
Button mLocalButton = view.findViewById(R.id.button_local_authentication);
mMicrosoftButton.setOnClickListener(v -> Tools.swapFragment(requireActivity(), MicrosoftLoginFragment.class, MicrosoftLoginFragment.TAG, null));
mLocalButton.setOnClickListener(v -> Tools.swapFragment(requireActivity(), LocalLoginFragment.class, LocalLoginFragment.TAG, null));
mLocalButton.setOnClickListener(v -> hasNoOnlineProfileDialog(requireActivity(), () -> Tools.swapFragment(requireActivity(), LocalLoginFragment.class, LocalLoginFragment.TAG, null)));
}
}

View File

@ -445,4 +445,9 @@
<string name="mg_renderer_summary_computeShaderext">May help with shaderpack glitches. Disable if not needed, can cause crashes.</string>
<string name="mg_renderer_title_errorSetting">Error Filtering</string>
<string name="app_short_name">Amethyst</string>
<string name="demo_versions_supported">Only Vanilla 1.3.1 and above are supported on demo accounts</string>
<string name="demo_unsupported">Demo Profile not supported</string>
<string name="change_account">Please change accounts to use this function</string>
<string name="no_minecraft_account_found">No Minecraft Account Found</string>
<string name="feature_requires_java_account">This feature requires a Microsoft account that owns Minecraft Java Edition.</string>
</resources>