From f8cddf344d2eda6f2bce6292c3af7a1496687055 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 6 Jun 2025 18:46:15 +0200 Subject: [PATCH 1/7] Android: Clear listener in SwitchSettingViewHolder If bind was called more than once for a SwitchSettingViewHolder, the line `binding.settingSwitch.isChecked = setting.isChecked` would accidentally trigger the listener registered during the previous bind call. --- .../features/settings/ui/viewholder/SwitchSettingViewHolder.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt index ddcf1d39b5c..2907b948b68 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt @@ -32,6 +32,9 @@ class SwitchSettingViewHolder( binding.textSettingName.text = item.name binding.textSettingDescription.text = item.description + // Make sure we don't trigger any listener set earlier + binding.settingSwitch.setOnCheckedChangeListener(null) + binding.settingSwitch.isChecked = setting.isChecked binding.settingSwitch.isEnabled = setting.isEditable From cff0ba76c1cfd8150b3f4ff2082579459829353a Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Thu, 24 Apr 2025 07:50:11 -0400 Subject: [PATCH 2/7] Init achievement manager in Android startup --- Source/Android/jni/MainAndroid.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 707e81e336a..7c78f49045b 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -33,6 +33,7 @@ #include "Common/Version.h" #include "Common/WindowSystemInfo.h" +#include "Core/AchievementManager.h" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/CommonTitles.h" @@ -559,6 +560,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Initialize(J WiimoteReal::InitAdapterClass(); UICommon::Init(); UICommon::InitControllers(WindowSystemInfo(WindowSystemType::Android, nullptr, nullptr, nullptr)); + + AchievementManager::GetInstance().Init(nullptr); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ReportStartToAnalytics(JNIEnv*, From b662cd93cec27540c15c3ab58bc9831863b9291b Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Thu, 24 Apr 2025 07:51:01 -0400 Subject: [PATCH 3/7] Add Achievements submenu to Android settings --- .../settings/model/AchievementModel.kt | 11 +++ .../features/settings/model/BooleanSetting.kt | 43 +++++++++- .../features/settings/model/Settings.kt | 2 + .../features/settings/ui/MenuTag.kt | 1 + .../features/settings/ui/SettingsFragment.kt | 1 + .../settings/ui/SettingsFragmentPresenter.kt | 82 +++++++++++++++++++ .../app/src/main/res/values/strings.xml | 9 ++ Source/Android/jni/AchievementAdapter.cpp | 24 ++++++ Source/Android/jni/CMakeLists.txt | 1 + Source/Android/jni/Config/NativeConfig.cpp | 4 + 10 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt create mode 100644 Source/Android/jni/AchievementAdapter.cpp diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt new file mode 100644 index 00000000000..345daf54a16 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.settings.model + +object AchievementModel { + @JvmStatic + external fun init() + + @JvmStatic + external fun shutdown() +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt index 0b6945ff130..1f8ef6e94bc 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt @@ -883,6 +883,42 @@ enum class BooleanSetting( Settings.SECTION_LOGGER_OPTIONS, "WriteToFile", false + ), + ACHIEVEMENTS_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "Enabled", + false + ), + ACHIEVEMENTS_HARDCORE_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "HardcoreEnabled", + false + ), + ACHIEVEMENTS_UNOFFICIAL_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "UnofficialEnabled", + false + ), + ACHIEVEMENTS_ENCORE_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "EncoreEnabled", + false + ), + ACHIEVEMENTS_SPECTATOR_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "SpectatorEnabled", + false + ), + ACHIEVEMENTS_PROGRESS_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "ProgressEnabled", + true ); override val isOverridden: Boolean @@ -943,7 +979,12 @@ enum class BooleanSetting( MAIN_TIME_TRACKING, MAIN_EMULATE_SKYLANDER_PORTAL, MAIN_EMULATE_INFINITY_BASE, - MAIN_EMULATE_WII_SPEAK + MAIN_EMULATE_WII_SPEAK, + ACHIEVEMENTS_ENABLED, + ACHIEVEMENTS_HARDCORE_ENABLED, + ACHIEVEMENTS_UNOFFICIAL_ENABLED, + ACHIEVEMENTS_ENCORE_ENABLED, + ACHIEVEMENTS_SPECTATOR_ENABLED ) private val NOT_RUNTIME_EDITABLE: Set = HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY)) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt index 32ad11b3e1f..9f91a4244c9 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt @@ -104,6 +104,7 @@ class Settings : Closeable { const val FILE_GFX = "GFX" const val FILE_LOGGER = "Logger" const val FILE_WIIMOTE = "WiimoteNew" + const val FILE_ACHIEVEMENTS = "RetroAchievements" const val FILE_GAME_SETTINGS_ONLY = "GameSettingsOnly" const val SECTION_INI_ANDROID = "Android" const val SECTION_INI_ANDROID_OVERLAY_BUTTONS = "AndroidOverlayButtons" @@ -122,5 +123,6 @@ class Settings : Closeable { const val SECTION_EMULATED_USB_DEVICES = "EmulatedUSBDevices" const val SECTION_STEREOSCOPY = "Stereoscopy" const val SECTION_ANALYTICS = "Analytics" + const val SECTION_ACHIEVEMENTS = "Achievements" } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt index 0bfcb96d6ce..74556b07d97 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt @@ -14,6 +14,7 @@ enum class MenuTag { CONFIG_GAME_CUBE("config_gamecube"), CONFIG_SERIALPORT1("config_serialport1"), CONFIG_WII("config_wii"), + CONFIG_ACHIEVEMENTS("config_achievements"), CONFIG_ADVANCED("config_advanced"), CONFIG_LOG("config_log"), DEBUG("debug"), diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt index 991d3c3c2b9..513769a50da 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt @@ -268,6 +268,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView { titles[MenuTag.CONFIG_GAME_CUBE] = R.string.gamecube_submenu titles[MenuTag.CONFIG_SERIALPORT1] = R.string.serialport1_submenu titles[MenuTag.CONFIG_WII] = R.string.wii_submenu + titles[MenuTag.CONFIG_ACHIEVEMENTS] = R.string.achievements_submenu titles[MenuTag.CONFIG_ADVANCED] = R.string.advanced_submenu titles[MenuTag.DEBUG] = R.string.debug_submenu titles[MenuTag.GRAPHICS] = R.string.graphics_settings diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt index 25acccb2fc8..a5ee2f28df0 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt @@ -111,6 +111,7 @@ class SettingsFragmentPresenter( MenuTag.CONFIG_PATHS -> addPathsSettings(sl) MenuTag.CONFIG_GAME_CUBE -> addGameCubeSettings(sl) MenuTag.CONFIG_WII -> addWiiSettings(sl) + MenuTag.CONFIG_ACHIEVEMENTS -> addAchievementSettings(sl); MenuTag.CONFIG_ADVANCED -> addAdvancedSettings(sl) MenuTag.GRAPHICS -> addGraphicsSettings(sl) MenuTag.CONFIG_SERIALPORT1 -> addSerialPortSubSettings(sl, serialPort1Type) @@ -200,6 +201,7 @@ class SettingsFragmentPresenter( sl.add(SubmenuSetting(context, R.string.paths_submenu, MenuTag.CONFIG_PATHS)) sl.add(SubmenuSetting(context, R.string.gamecube_submenu, MenuTag.CONFIG_GAME_CUBE)) sl.add(SubmenuSetting(context, R.string.wii_submenu, MenuTag.CONFIG_WII)) + sl.add(SubmenuSetting(context, R.string.achievements_submenu, MenuTag.CONFIG_ACHIEVEMENTS)) sl.add(SubmenuSetting(context, R.string.advanced_submenu, MenuTag.CONFIG_ADVANCED)) sl.add(SubmenuSetting(context, R.string.log_submenu, MenuTag.CONFIG_LOG)) sl.add(SubmenuSetting(context, R.string.debug_submenu, MenuTag.DEBUG)) @@ -914,6 +916,86 @@ class SettingsFragmentPresenter( ) } + private fun addAchievementSettings(sl: ArrayList) { + val achievementsEnabledSetting: AbstractBooleanSetting = object : AbstractBooleanSetting { + override val boolean: Boolean + get() = BooleanSetting.ACHIEVEMENTS_ENABLED.boolean + + override fun setBoolean(settings: Settings, newValue: Boolean) { + BooleanSetting.ACHIEVEMENTS_ENABLED.setBoolean(settings, newValue) + if (newValue) + AchievementModel.init() + else + AchievementModel.shutdown() + loadSettingsList() + } + + override val isOverridden: Boolean + get() = BooleanSetting.ACHIEVEMENTS_ENABLED.isOverridden + + override val isRuntimeEditable: Boolean + get() = BooleanSetting.ACHIEVEMENTS_ENABLED.isRuntimeEditable + + override fun delete(settings: Settings): Boolean { + val result = BooleanSetting.ACHIEVEMENTS_ENABLED.delete(settings) + AchievementModel.shutdown() + loadSettingsList() + return result + } + } + + sl.add( + SwitchSetting( + context, + achievementsEnabledSetting, + R.string.achievements_enabled, + 0 + ) + ) + if (BooleanSetting.ACHIEVEMENTS_ENABLED.boolean) { + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_HARDCORE_ENABLED, + R.string.achievements_hardcore_enabled, + 0 + ) + ) + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_UNOFFICIAL_ENABLED, + R.string.achievements_unofficial_enabled, + 0 + ) + ) + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_ENCORE_ENABLED, + R.string.achievements_encore_enabled, + 0 + ) + ) + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_SPECTATOR_ENABLED, + R.string.achievements_spectator_enabled, + 0 + ) + ) + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_PROGRESS_ENABLED, + R.string.achievements_progress_enabled, + 0 + ) + ) + } + } + private fun addAdvancedSettings(sl: ArrayList) { val SYNC_GPU_NEVER = 0 val SYNC_GPU_ON_IDLE_SKIP = 1 diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 6342e35cb02..67ac68f75ef 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -75,6 +75,7 @@ Enable Cheats Speed Limit (0% = Unlimited) WARNING: Changing this from the default (100%) WILL break games and cause glitches. Please do not report bugs that occur with a non-default clock. + RetroAchievements GameCube IPL Settings Skip Main Menu @@ -953,4 +954,12 @@ It can efficiently compress both junk data and encrypted Wii data. Mute Wii Speak Missing Microphone Permission Wii Speak emulation requires microphone permission. You might need to restart the game for the permission to be effective. + + + Enable Achievements + Enable Hardcore Mode + Enable Unofficial Achievements + Enable Encore Mode + Enable Spectator Mode + Enable Progress Notifications diff --git a/Source/Android/jni/AchievementAdapter.cpp b/Source/Android/jni/AchievementAdapter.cpp new file mode 100644 index 00000000000..119ecbbd6fb --- /dev/null +++ b/Source/Android/jni/AchievementAdapter.cpp @@ -0,0 +1,24 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "Core/AchievementManager.h" +#include "jni/AndroidCommon/AndroidCommon.h" + +extern "C" { + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_init(JNIEnv* env, jclass) +{ + AchievementManager::GetInstance().Init(nullptr); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_shutdown(JNIEnv* env, + jclass) +{ + AchievementManager::GetInstance().Shutdown(); +} + +} // extern "C" diff --git a/Source/Android/jni/CMakeLists.txt b/Source/Android/jni/CMakeLists.txt index be200affa9b..b825fa314b6 100644 --- a/Source/Android/jni/CMakeLists.txt +++ b/Source/Android/jni/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(main SHARED + AchievementAdapter.cpp ActivityTracker.cpp Cheats/ARCheat.cpp Cheats/Cheats.h diff --git a/Source/Android/jni/Config/NativeConfig.cpp b/Source/Android/jni/Config/NativeConfig.cpp index f367c5e1627..8478174dae2 100644 --- a/Source/Android/jni/Config/NativeConfig.cpp +++ b/Source/Android/jni/Config/NativeConfig.cpp @@ -48,6 +48,10 @@ static Config::Location GetLocation(JNIEnv* env, jstring file, jstring section, { system = Config::System::GameSettingsOnly; } + else if (decoded_file == "RetroAchievements") + { + system = Config::System::Achievements; + } else { ASSERT(false); From 98678e9a8b713ff8bb8aa5d1c58f44e8b57a16fc Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Fri, 13 Jun 2025 20:35:24 -0400 Subject: [PATCH 4/7] AchievementManager - Add Android to user agent If the build is an Android build, identify it as such in the AchievementManager user agent so that android builds can be tracked separately for debug purposes. --- Source/Core/Core/AchievementManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 5423bb29e03..a319499d09e 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -49,8 +49,13 @@ #include #endif // RC_CLIENT_SUPPORTS_RAINTEGRATION +#ifdef ANDROID +static const Common::HttpRequest::Headers USER_AGENT_HEADER = { + {"User-Agent", Common::GetUserAgentStr() + " (Android)"}}; +#else // ANDROID static const Common::HttpRequest::Headers USER_AGENT_HEADER = { {"User-Agent", Common::GetUserAgentStr()}}; +#endif // ANDROID AchievementManager& AchievementManager::GetInstance() { From f4f26a26d22e0c4be99a699277e5dfe2f1bbe652 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Sun, 27 Apr 2025 09:15:01 -0400 Subject: [PATCH 5/7] Add login to achievement settings --- .../settings/model/AchievementModel.kt | 6 ++ .../features/settings/model/StringSetting.kt | 12 +++ .../features/settings/ui/LoginDialog.kt | 51 ++++++++++++ .../settings/ui/SettingsFragmentPresenter.kt | 28 +++++++ .../app/src/main/res/layout/dialog_login.xml | 78 +++++++++++++++++++ .../app/src/main/res/values/strings.xml | 4 + Source/Android/jni/AchievementAdapter.cpp | 13 ++++ 7 files changed, 192 insertions(+) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/LoginDialog.kt create mode 100644 Source/Android/app/src/main/res/layout/dialog_login.xml diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt index 345daf54a16..6626ba0df35 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt @@ -6,6 +6,12 @@ object AchievementModel { @JvmStatic external fun init() + @JvmStatic + external fun login(password: String) + + @JvmStatic + external fun logout() + @JvmStatic external fun shutdown() } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt index b150c845e18..29640aa92f4 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt @@ -80,6 +80,18 @@ enum class StringSetting( Settings.SECTION_GFX_SETTINGS, "DriverLibName", "" + ), + ACHIEVEMENTS_USERNAME( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "Username", + "" + ), + ACHIEVEMENTS_API_TOKEN( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "ApiToken", + "" ); override val isOverridden: Boolean diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/LoginDialog.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/LoginDialog.kt new file mode 100644 index 00000000000..f49c9ff9224 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/LoginDialog.kt @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.settings.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import org.dolphinemu.dolphinemu.databinding.DialogLoginBinding +import org.dolphinemu.dolphinemu.features.settings.model.AchievementModel.login +import org.dolphinemu.dolphinemu.features.settings.model.NativeConfig +import org.dolphinemu.dolphinemu.features.settings.model.StringSetting + +class LoginDialog : DialogFragment() { + private var _binding: DialogLoginBinding? = null + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = DialogLoginBinding.inflate(inflater, container, false) + binding.usernameInput.setText( + StringSetting.ACHIEVEMENTS_USERNAME.string + ) + return binding.getRoot() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + binding.buttonCancel.setOnClickListener { onCancelClicked() } + binding.buttonLogin.setOnClickListener { onLoginClicked() } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + private fun onCancelClicked() { + dismiss() + } + + private fun onLoginClicked() { + StringSetting.ACHIEVEMENTS_USERNAME.setString(NativeConfig.LAYER_BASE_OR_CURRENT, + binding.usernameInput.text.toString()) + login(binding.passwordInput.text.toString()) + dismiss() + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt index a5ee2f28df0..0fd8a97782b 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt @@ -31,6 +31,7 @@ import org.dolphinemu.dolphinemu.features.input.ui.ProfileDialog import org.dolphinemu.dolphinemu.features.input.ui.ProfileDialogPresenter import org.dolphinemu.dolphinemu.features.settings.model.* import org.dolphinemu.dolphinemu.features.settings.model.view.* +import org.dolphinemu.dolphinemu.features.settings.model.AchievementModel.logout import org.dolphinemu.dolphinemu.model.GpuDriverMetadata import org.dolphinemu.dolphinemu.ui.main.MainPresenter import org.dolphinemu.dolphinemu.utils.* @@ -953,6 +954,33 @@ class SettingsFragmentPresenter( ) ) if (BooleanSetting.ACHIEVEMENTS_ENABLED.boolean) { + if (StringSetting.ACHIEVEMENTS_API_TOKEN.string == "") { + sl.add( + RunRunnable( + context, + R.string.achievements_login, + 0, + 0, + 0, + false + ) { + fragmentView.showDialogFragment(LoginDialog()) + loadSettingsList() + }) + } else { + sl.add( + RunRunnable( + context, + R.string.achievements_logout, + 0, + 0, + 0, + false + ) { + logout() + loadSettingsList() + }) + } sl.add( SwitchSetting( context, diff --git a/Source/Android/app/src/main/res/layout/dialog_login.xml b/Source/Android/app/src/main/res/layout/dialog_login.xml new file mode 100644 index 00000000000..a8b2b3228c5 --- /dev/null +++ b/Source/Android/app/src/main/res/layout/dialog_login.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + +