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:
1 parent
1e0f6a557e
commit
ddced1a070
8 files changed
+87
-12
No files matched your search
+10
-1
@@ -2,12 +2,21 @@
|
|||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
object AchievementModel {
|
object AchievementModel {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun init()
|
external fun init()
|
||||||
|
|
||||||
|
suspend fun asyncLogin(password: String): Boolean {
|
||||||
|
return withContext(Dispatchers.IO) {
|
||||||
|
login(password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun login(password: String)
|
private external fun login(password: String): Boolean
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun logout()
|
external fun logout()
|
||||||
|
|||||||
+16
-4
@@ -7,12 +7,15 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.dolphinemu.dolphinemu.databinding.DialogLoginBinding
|
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.NativeConfig
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting
|
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting
|
||||||
|
|
||||||
class LoginDialog : DialogFragment() {
|
class LoginDialog(val parent: SettingsFragmentPresenter) : DialogFragment() {
|
||||||
private var _binding: DialogLoginBinding? = null
|
private var _binding: DialogLoginBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
@@ -43,9 +46,18 @@ class LoginDialog : DialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun onLoginClicked() {
|
private fun onLoginClicked() {
|
||||||
|
binding.loginFailed.visibility = View.GONE
|
||||||
|
binding.loginInProgress.visibility = View.VISIBLE
|
||||||
StringSetting.ACHIEVEMENTS_USERNAME.setString(NativeConfig.LAYER_BASE_OR_CURRENT,
|
StringSetting.ACHIEVEMENTS_USERNAME.setString(NativeConfig.LAYER_BASE_OR_CURRENT,
|
||||||
binding.usernameInput.text.toString())
|
binding.usernameInput.text.toString())
|
||||||
login(binding.passwordInput.text.toString())
|
lifecycleScope.launch {
|
||||||
dismiss()
|
if (asyncLogin(binding.passwordInput.text.toString())) {
|
||||||
|
parent.loadSettingsList()
|
||||||
|
dismiss()
|
||||||
|
} else {
|
||||||
|
binding.loginInProgress.visibility = View.GONE
|
||||||
|
binding.loginFailed.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -101,7 +101,7 @@ class SettingsFragmentPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSettingsList() {
|
fun loadSettingsList() {
|
||||||
val sl = ArrayList<SettingsItem>()
|
val sl = ArrayList<SettingsItem>()
|
||||||
when (menuTag) {
|
when (menuTag) {
|
||||||
MenuTag.SETTINGS -> addTopLevelSettings(sl)
|
MenuTag.SETTINGS -> addTopLevelSettings(sl)
|
||||||
@@ -964,7 +964,7 @@ class SettingsFragmentPresenter(
|
|||||||
0,
|
0,
|
||||||
false
|
false
|
||||||
) {
|
) {
|
||||||
fragmentView.showDialogFragment(LoginDialog())
|
fragmentView.showDialogFragment(LoginDialog(this))
|
||||||
loadSettingsList()
|
loadSettingsList()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="@dimen/spacing_large"
|
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_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/username">
|
app:layout_constraintTop_toBottomOf="@id/username">
|
||||||
@@ -53,6 +53,38 @@
|
|||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</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
|
<Button
|
||||||
android:id="@+id/button_cancel"
|
android:id="@+id/button_cancel"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -62,7 +94,7 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@id/button_login"
|
app:layout_constraintEnd_toStartOf="@id/button_login"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/password" />
|
app:layout_constraintTop_toBottomOf="@id/login_failed" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_login"
|
android:id="@+id/button_login"
|
||||||
@@ -73,6 +105,6 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/button_cancel"
|
app:layout_constraintStart_toEndOf="@id/button_cancel"
|
||||||
app:layout_constraintTop_toBottomOf="@id/password" />
|
app:layout_constraintTop_toBottomOf="@id/login_failed" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</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_password">Password</string>
|
||||||
<string name="achievements_login">Log In</string>
|
<string name="achievements_login">Log In</string>
|
||||||
<string name="achievements_logout">Log Out</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>
|
</resources>
|
||||||
@@ -3,8 +3,12 @@
|
|||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include <latch>
|
||||||
|
#include "Common/Event.h"
|
||||||
|
#include "Common/HookableEvent.h"
|
||||||
#include "Core/AchievementManager.h"
|
#include "Core/AchievementManager.h"
|
||||||
#include "jni/AndroidCommon/AndroidCommon.h"
|
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||||
|
#include "jni/AndroidCommon/IDCache.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
@@ -14,11 +18,21 @@ Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_init(JNI
|
|||||||
AchievementManager::GetInstance().Init(nullptr);
|
AchievementManager::GetInstance().Init(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_login(JNIEnv* env, jclass,
|
Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_login(JNIEnv* env, jclass,
|
||||||
jstring password)
|
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
|
JNIEXPORT void JNICALL
|
||||||
|
|||||||
@@ -934,6 +934,7 @@ void AchievementManager::LoginCallback(int result, const char* error_message, rc
|
|||||||
Config::Get(Config::RA_USERNAME));
|
Config::Get(Config::RA_USERNAME));
|
||||||
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
|
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
|
||||||
instance.update_event.Trigger({.failed_login_code = result});
|
instance.update_event.Trigger({.failed_login_code = result});
|
||||||
|
instance.login_event.Trigger(result);
|
||||||
return;
|
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.");
|
WARN_LOG_FMT(ACHIEVEMENTS, "Failed to retrieve user information from client.");
|
||||||
instance.update_event.Trigger({.failed_login_code = RC_INVALID_STATE});
|
instance.update_event.Trigger({.failed_login_code = RC_INVALID_STATE});
|
||||||
|
instance.login_event.Trigger(RC_INVALID_STATE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,9 +967,12 @@ void AchievementManager::LoginCallback(int result, const char* error_message, rc
|
|||||||
user->username, Config::Get(Config::RA_USERNAME));
|
user->username, Config::Get(Config::RA_USERNAME));
|
||||||
rc_client_logout(client);
|
rc_client_logout(client);
|
||||||
instance.update_event.Trigger({.failed_login_code = RC_INVALID_STATE});
|
instance.update_event.Trigger({.failed_login_code = RC_INVALID_STATE});
|
||||||
|
instance.login_event.Trigger(RC_INVALID_STATE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
instance.login_event.Trigger(RC_OK);
|
||||||
|
|
||||||
INFO_LOG_FMT(ACHIEVEMENTS, "Successfully logged in {} to RetroAchievements server.",
|
INFO_LOG_FMT(ACHIEVEMENTS, "Successfully logged in {} to RetroAchievements server.",
|
||||||
user->username);
|
user->username);
|
||||||
std::lock_guard lg{instance.GetLock()};
|
std::lock_guard lg{instance.GetLock()};
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ public:
|
|||||||
int failed_login_code = 0;
|
int failed_login_code = 0;
|
||||||
};
|
};
|
||||||
Common::HookableEvent<const UpdatedItems&> update_event;
|
Common::HookableEvent<const UpdatedItems&> update_event;
|
||||||
|
Common::HookableEvent<int> login_event;
|
||||||
|
|
||||||
static AchievementManager& GetInstance();
|
static AchievementManager& GetInstance();
|
||||||
void Init(void* hwnd);
|
void Init(void* hwnd);
|
||||||
|
|||||||
Reference in new issue
Block a user