mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-12-16 04:09:39 +00:00
RetroAchievements - Android login callback
Modify the RetroAchievements login code in Android to pass in a callback, pop a message if login fails, close the login box if it succeeds.
This commit is contained in:
parent
1e0f6a557e
commit
ddced1a070
@ -2,12 +2,21 @@
|
||||
|
||||
package org.dolphinemu.dolphinemu.features.settings.model
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
object AchievementModel {
|
||||
@JvmStatic
|
||||
external fun init()
|
||||
|
||||
suspend fun asyncLogin(password: String): Boolean {
|
||||
return withContext(Dispatchers.IO) {
|
||||
login(password)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
external fun login(password: String)
|
||||
private external fun login(password: String): Boolean
|
||||
|
||||
@JvmStatic
|
||||
external fun logout()
|
||||
|
||||
@ -7,12 +7,15 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.dolphinemu.dolphinemu.databinding.DialogLoginBinding
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.AchievementModel.login
|
||||
import org.dolphinemu.dolphinemu.dialogs.AlertMessage
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.AchievementModel.asyncLogin
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.NativeConfig
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting
|
||||
|
||||
class LoginDialog : DialogFragment() {
|
||||
class LoginDialog(val parent: SettingsFragmentPresenter) : DialogFragment() {
|
||||
private var _binding: DialogLoginBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
@ -43,9 +46,18 @@ class LoginDialog : DialogFragment() {
|
||||
}
|
||||
|
||||
private fun onLoginClicked() {
|
||||
binding.loginFailed.visibility = View.GONE
|
||||
binding.loginInProgress.visibility = View.VISIBLE
|
||||
StringSetting.ACHIEVEMENTS_USERNAME.setString(NativeConfig.LAYER_BASE_OR_CURRENT,
|
||||
binding.usernameInput.text.toString())
|
||||
login(binding.passwordInput.text.toString())
|
||||
dismiss()
|
||||
lifecycleScope.launch {
|
||||
if (asyncLogin(binding.passwordInput.text.toString())) {
|
||||
parent.loadSettingsList()
|
||||
dismiss()
|
||||
} else {
|
||||
binding.loginInProgress.visibility = View.GONE
|
||||
binding.loginFailed.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ class SettingsFragmentPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadSettingsList() {
|
||||
fun loadSettingsList() {
|
||||
val sl = ArrayList<SettingsItem>()
|
||||
when (menuTag) {
|
||||
MenuTag.SETTINGS -> addTopLevelSettings(sl)
|
||||
@ -964,7 +964,7 @@ class SettingsFragmentPresenter(
|
||||
0,
|
||||
false
|
||||
) {
|
||||
fragmentView.showDialogFragment(LoginDialog())
|
||||
fragmentView.showDialogFragment(LoginDialog(this))
|
||||
loadSettingsList()
|
||||
})
|
||||
} else {
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/spacing_large"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_cancel"
|
||||
app:layout_constraintBottom_toTopOf="@id/login_in_progress"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/username">
|
||||
@ -53,6 +53,38 @@
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_in_progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:text="@string/achievements_login_in_progress"
|
||||
android:textAlignment="center"
|
||||
android:textColor="?attr/colorOnErrorContainer"
|
||||
android:visibility="invisible"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
app:layout_constraintBottom_toTopOf="@id/login_failed"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/password"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_failed"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:text="@string/achievements_login_failed"
|
||||
android:textAlignment="center"
|
||||
android:textColor="?attr/colorOnErrorContainer"
|
||||
android:visibility="invisible"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_cancel"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_in_progress"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_cancel"
|
||||
android:layout_width="0dp"
|
||||
@ -62,7 +94,7 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/button_login"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/password" />
|
||||
app:layout_constraintTop_toBottomOf="@id/login_failed" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_login"
|
||||
@ -73,6 +105,6 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/button_cancel"
|
||||
app:layout_constraintTop_toBottomOf="@id/password" />
|
||||
app:layout_constraintTop_toBottomOf="@id/login_failed" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@ -966,4 +966,6 @@ It can efficiently compress both junk data and encrypted Wii data.
|
||||
<string name="achievements_password">Password</string>
|
||||
<string name="achievements_login">Log In</string>
|
||||
<string name="achievements_logout">Log Out</string>
|
||||
<string name="achievements_login_in_progress">Logging In</string>
|
||||
<string name="achievements_login_failed">Login Failed</string>
|
||||
</resources>
|
||||
|
||||
@ -3,8 +3,12 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <latch>
|
||||
#include "Common/Event.h"
|
||||
#include "Common/HookableEvent.h"
|
||||
#include "Core/AchievementManager.h"
|
||||
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||
#include "jni/AndroidCommon/IDCache.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -14,11 +18,21 @@ Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_init(JNI
|
||||
AchievementManager::GetInstance().Init(nullptr);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_login(JNIEnv* env, jclass,
|
||||
jstring password)
|
||||
{
|
||||
AchievementManager::GetInstance().Login(GetJString(env, password));
|
||||
auto& instance = AchievementManager::GetInstance();
|
||||
bool success;
|
||||
std::latch login_complete_event{1};
|
||||
Common::EventHook login_hook =
|
||||
instance.login_event.Register([&login_complete_event, &success](int result) {
|
||||
success = (result == RC_OK);
|
||||
login_complete_event.count_down();
|
||||
});
|
||||
instance.Login(GetJString(env, password));
|
||||
login_complete_event.wait();
|
||||
return success;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
|
||||
@ -934,6 +934,7 @@ void AchievementManager::LoginCallback(int result, const char* error_message, rc
|
||||
Config::Get(Config::RA_USERNAME));
|
||||
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
|
||||
instance.update_event.Trigger({.failed_login_code = result});
|
||||
instance.login_event.Trigger(result);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -946,6 +947,7 @@ void AchievementManager::LoginCallback(int result, const char* error_message, rc
|
||||
{
|
||||
WARN_LOG_FMT(ACHIEVEMENTS, "Failed to retrieve user information from client.");
|
||||
instance.update_event.Trigger({.failed_login_code = RC_INVALID_STATE});
|
||||
instance.login_event.Trigger(RC_INVALID_STATE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -965,9 +967,12 @@ void AchievementManager::LoginCallback(int result, const char* error_message, rc
|
||||
user->username, Config::Get(Config::RA_USERNAME));
|
||||
rc_client_logout(client);
|
||||
instance.update_event.Trigger({.failed_login_code = RC_INVALID_STATE});
|
||||
instance.login_event.Trigger(RC_INVALID_STATE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
instance.login_event.Trigger(RC_OK);
|
||||
|
||||
INFO_LOG_FMT(ACHIEVEMENTS, "Successfully logged in {} to RetroAchievements server.",
|
||||
user->username);
|
||||
std::lock_guard lg{instance.GetLock()};
|
||||
|
||||
@ -121,6 +121,7 @@ public:
|
||||
int failed_login_code = 0;
|
||||
};
|
||||
Common::HookableEvent<const UpdatedItems&> update_event;
|
||||
Common::HookableEvent<int> login_event;
|
||||
|
||||
static AchievementManager& GetInstance();
|
||||
void Init(void* hwnd);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user