This commit is contained in:
LillyJadeKatrin 2025-04-27 16:09:10 +00:00 committed by GitHub
commit 2d5f790310
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 357 additions and 0 deletions

View file

@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.dialogs
import android.app.Dialog
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
class LoginDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = MaterialAlertDialogBuilder(requireContext())
.setMessage(requireArguments().getInt(KEY_MESSAGE))
.setPositiveButton(android.R.string.ok, null)
return dialog.create()
}
companion object {
const val TAG = "NotificationDialog"
const val KEY_MESSAGE = "message"
}
}

View file

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.settings.model
import androidx.annotation.Keep
object AchievementModel {
@JvmStatic
external fun login(password: String)
@JvmStatic
external fun logout()
}

View file

@ -865,6 +865,42 @@ enum class BooleanSetting(
Settings.SECTION_LOGGER_OPTIONS,
"WriteToFile",
false
),
ACHIEVEMENTS_ENABLED(
Settings.FILE_ACHIEVEMENTS,
Settings.SECTION_ACHIEVEMENTS,
"Enabled",
true
),
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

View file

@ -115,6 +115,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"
@ -133,5 +134,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"
}
}

View file

@ -0,0 +1,45 @@
// 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.FragmentLoginBinding
import org.dolphinemu.dolphinemu.features.settings.model.AchievementModel.login
class LoginFragment : DialogFragment() {
private var _binding: FragmentLoginBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentLoginBinding.inflate(inflater, container, false)
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() {
// close?
}
private fun onLoginClicked() {
// Set username in settings
login(binding.passwordInput.text.toString())
// close?
}
}

View file

@ -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"),

View file

@ -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

View file

@ -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.*
@ -115,6 +116,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)
@ -204,6 +206,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))
@ -902,6 +905,75 @@ class SettingsFragmentPresenter(
)
}
private fun addAchievementSettings(sl: ArrayList<SettingsItem>) {
sl.add(
SwitchSetting(
context,
BooleanSetting.ACHIEVEMENTS_ENABLED,
R.string.achievements_enabled,
0
)
)
sl.add(
RunRunnable(
context,
R.string.achievements_login,
0,
0,
0,
true
) { fragmentView.showDialogFragment(LoginFragment()) })
sl.add(
RunRunnable(
context,
R.string.achievements_logout,
0,
0,
0,
true
) { logout() })
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<SettingsItem>) {
val SYNC_GPU_NEVER = 0
val SYNC_GPU_ON_IDLE_SKIP = 1

View file

@ -0,0 +1,111 @@
<?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:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/button_layout">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/spacing_large"
android:layout_marginVertical="@dimen/spacing_small"
android:hint="@string/achievements_username"
android:paddingTop="@dimen/spacing_medlarge"
app:errorEnabled="true"
app:layout_constraintBottom_toTopOf="@id/password"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/username_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="text"
android:minHeight="48dp"
android:textAlignment="viewStart" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/achievements_password"
android:layout_marginHorizontal="@dimen/spacing_large"
android:layout_marginBottom="24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/username"
app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:importantForAutofill="no"
android:inputType="text"
android:textAlignment="viewStart" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/button_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/scroll_view">
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/spacing_large"
android:text="@string/cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/button_ok"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button_login"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/spacing_large"
android:text="@string/ok"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/button_cancel"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -77,6 +77,9 @@
<string name="enable_cheats">Enable Cheats</string>
<string name="speed_limit">Speed Limit (0% = Unlimited)</string>
<string name="overclock_warning">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.</string>
<string name="achievements_submenu">Achievements</string>
<string name="achievements_login_submenu">RetroAchievements Login</string>
<string name="achievements_settings">Achievements</string>
<string name="gamecube_submenu">GameCube</string>
<string name="ipl_settings">IPL Settings</string>
<string name="skip_main_menu">Skip Main Menu</string>
@ -944,4 +947,16 @@ It can efficiently compress both junk data and encrypted Wii data.
<string name="incompatible_figure_selected">Incompatible Figure Selected</string>
<string name="select_compatible_figure">Please select a compatible figure file</string>
<!-- Achievements -->
<string name="achievements_enabled">Enable Achievements</string>
<string name="achievements_hardcore_enabled">Enable Hardcore Mode</string>
<string name="achievements_unofficial_enabled">Enable Unofficial Achievements</string>
<string name="achievements_encore_enabled">Enable Encore Mode</string>
<string name="achievements_spectator_enabled">Enable Spectator Mode</string>
<string name="achievements_discord_presence_enabled">Enable Discord Presence</string>
<string name="achievements_progress_enabled">Enable Progress Notifications</string>
<string name="achievements_username">Username</string>
<string name="achievements_password">Password</string>
<string name="achievements_login">Login</string>
<string name="achievements_logout">Logout</string>
</resources>

View file

@ -0,0 +1,33 @@
// Copyright 2021 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <string>
#include <vector>
#include <jni.h>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Core/AchievementManager.h"
#include "jni/AndroidCommon/AndroidCommon.h"
#include "jni/AndroidCommon/IDCache.h"
#include "jni/Cheats/Cheats.h"
extern "C" {
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_login(JNIEnv* env, jclass, jstring password)
{
AchievementManager::GetInstance().Login(GetJString(env, password));
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_logout(JNIEnv* env, jclass)
{
AchievementManager::GetInstance().Logout();
}
} // extern "C"

View file

@ -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);

View file

@ -34,6 +34,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"
@ -577,6 +578,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*,