feat(discord): custom buttons (#295)

* feat(discord): custom buttons

* feat(discord): added haptics

* fine...

* fix(strings): my genius is frightening

* feat: add option to only show the first button

* feat: discord rpc menu

* feat(link): add button preview back

---------

Co-authored-by: aayush262 <aayushthakur262006@gmail.com>
This commit is contained in:
ibo 2024-04-02 05:09:52 +02:00 committed by GitHub
parent 86427a4c3c
commit aabbe9198a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 292 additions and 59 deletions

View file

@ -1084,35 +1084,40 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if ((isOnline(context) && !offline) && Discord.token != null && !incognito) { if ((isOnline(context) && !offline) && Discord.token != null && !incognito) {
lifecycleScope.launch { lifecycleScope.launch {
val presence = RPC.createPresence(RPC.Companion.RPCData( val discordMode = PrefManager.getCustomVal("discord_mode", "dantotsu")
applicationId = Discord.application_Id, val buttons = when (discordMode) {
type = RPC.Type.WATCHING, "nothing" -> mutableListOf(
activityName = media.userPreferredName,
details = ep.title?.takeIf { it.isNotEmpty() } ?: getString(
R.string.episode_num,
ep.number
),
state = "Episode : ${ep.number}/${media.anime?.totalEpisodes ?: "??"}",
largeImage = media.cover?.let {
RPC.Link(
media.userPreferredName,
it
)
},
smallImage = RPC.Link(
"Dantotsu",
Discord.small_Image
),
buttons = mutableListOf(
RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""),
RPC.Link( )
"Stream on Dantotsu", "dantotsu" -> mutableListOf(
getString(R.string.github) RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""),
RPC.Link("Watch on Dantotsu", getString(R.string.dantotsu))
)
"anilist" -> {
val userId = PrefManager.getVal<String>(PrefName.AnilistUserId)
val anilistLink = "https://anilist.co/user/$userId/"
mutableListOf(
RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""),
RPC.Link("View My AniList", anilistLink)
) )
}
else -> mutableListOf()
}
val presence = RPC.createPresence(
RPC.Companion.RPCData(
applicationId = Discord.application_Id,
type = RPC.Type.WATCHING,
activityName = media.userPreferredName,
details = ep.title?.takeIf { it.isNotEmpty() } ?: getString(
R.string.episode_num,
ep.number
),
state = "Episode : ${ep.number}/${media.anime?.totalEpisodes ?: "??"}",
largeImage = media.cover?.let { RPC.Link(media.userPreferredName, it) },
smallImage = RPC.Link("Dantotsu", Discord.small_Image),
buttons = buttons
) )
) )
)
val intent = Intent(context, DiscordService::class.java).apply { val intent = Intent(context, DiscordService::class.java).apply {
putExtra("presence", presence) putExtra("presence", presence)
} }
@ -1120,7 +1125,6 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
startService(intent) startService(intent)
} }
} }
updateProgress() updateProgress()
} }
} }

View file

@ -362,15 +362,11 @@ class MangaReaderActivity : AppCompatActivity() {
currentChapterIndex = chaptersArr.indexOf(chap.number) currentChapterIndex = chaptersArr.indexOf(chap.number)
binding.mangaReaderChapterSelect.setSelection(currentChapterIndex) binding.mangaReaderChapterSelect.setSelection(currentChapterIndex)
if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) {
binding.mangaReaderNextChap.text = binding.mangaReaderNextChap.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: ""
chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: "" binding.mangaReaderPrevChap.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: ""
binding.mangaReaderPrevChap.text =
chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: ""
} else { } else {
binding.mangaReaderNextChap.text = binding.mangaReaderNextChap.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: ""
chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: "" binding.mangaReaderPrevChap.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: ""
binding.mangaReaderPrevChap.text =
chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: ""
} }
applySettings() applySettings()
val context = this val context = this
@ -378,6 +374,25 @@ class MangaReaderActivity : AppCompatActivity() {
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if ((isOnline(context) && !offline) && Discord.token != null && !incognito) { if ((isOnline(context) && !offline) && Discord.token != null && !incognito) {
lifecycleScope.launch { lifecycleScope.launch {
val discordMode = PrefManager.getCustomVal("discord_mode", "dantotsu")
val buttons = when (discordMode) {
"nothing" -> mutableListOf(
RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""),
)
"dantotsu" -> mutableListOf(
RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""),
RPC.Link("Read on Dantotsu", getString(R.string.dantotsu))
)
"anilist" -> {
val userId = PrefManager.getVal<String>(PrefName.AnilistUserId)
val anilistLink = "https://anilist.co/user/$userId/"
mutableListOf(
RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""),
RPC.Link("View My AniList", anilistLink)
)
}
else -> mutableListOf()
}
val presence = RPC.createPresence( val presence = RPC.createPresence(
RPC.Companion.RPCData( RPC.Companion.RPCData(
applicationId = Discord.application_Id, applicationId = Discord.application_Id,
@ -386,20 +401,9 @@ class MangaReaderActivity : AppCompatActivity() {
details = chap.title?.takeIf { it.isNotEmpty() } details = chap.title?.takeIf { it.isNotEmpty() }
?: getString(R.string.chapter_num, chap.number), ?: getString(R.string.chapter_num, chap.number),
state = "${chap.number}/${media.manga?.totalChapters ?: "??"}", state = "${chap.number}/${media.manga?.totalChapters ?: "??"}",
largeImage = media.cover?.let { cover -> largeImage = media.cover?.let { cover -> RPC.Link(media.userPreferredName, cover) },
RPC.Link(media.userPreferredName, cover) smallImage = RPC.Link("Dantotsu", Discord.small_Image),
}, buttons = buttons
smallImage = RPC.Link(
"Dantotsu",
Discord.small_Image
),
buttons = mutableListOf(
RPC.Link(getString(R.string.view_manga), media.shareLink ?: ""),
RPC.Link(
"Stream on Dantotsu",
getString(R.string.github)
)
)
) )
) )
val intent = Intent(context, DiscordService::class.java).apply { val intent = Intent(context, DiscordService::class.java).apply {

View file

@ -0,0 +1,60 @@
package ani.dantotsu.settings
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.BottomSheetDialogFragment
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.databinding.BottomSheetDiscordRpcBinding
import ani.dantotsu.profile.activity.UsersAdapter
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import com.google.android.material.bottomsheet.BottomSheetDialog
class DiscordDialogFragment: BottomSheetDialogFragment() {
private var _binding: BottomSheetDiscordRpcBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = BottomSheetDiscordRpcBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
when (PrefManager.getCustomVal("discord_mode", "dantotsu")) {
"nothing" -> binding.radioNothing.isChecked= true
"dantotsu" -> binding.radioDantotsu.isChecked = true
"anilist" -> binding.radioAnilist.isChecked = true
else -> binding.radioAnilist.isChecked = true
}
binding.anilistLinkPreview.text = getString(R.string.anilist_link, PrefManager.getVal<String>(PrefName.AnilistUserName))
binding.radioGroup.setOnCheckedChangeListener { _, checkedId ->
val mode = when (checkedId) {
binding.radioNothing.id -> "nothing"
binding.radioDantotsu.id -> "dantotsu"
binding.radioAnilist.id -> "anilist"
else -> "dantotsu"
}
PrefManager.setCustomVal("discord_mode", mode)
}
}
override fun onDestroy() {
_binding = null
super.onDestroy()
}
}

View file

@ -19,12 +19,15 @@ import android.view.ViewGroup
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.TextView import android.widget.TextView
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import android.view.HapticFeedbackConstants
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -79,6 +82,7 @@ import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.toast import ani.dantotsu.toast
import ani.dantotsu.util.Logger import ani.dantotsu.util.Logger
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputEditText
import eltos.simpledialogfragment.SimpleDialog import eltos.simpledialogfragment.SimpleDialog
import eltos.simpledialogfragment.SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE import eltos.simpledialogfragment.SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE
@ -259,18 +263,18 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
reload() reload()
} }
imageSwitcher.visibility = View.VISIBLE settingsImageSwitcher.visibility = View.VISIBLE
var initialStatus = when (PrefManager.getVal<String>(PrefName.DiscordStatus)) { var initialStatus = when (PrefManager.getVal<String>(PrefName.DiscordStatus)) {
"online" -> R.drawable.discord_status_online "online" -> R.drawable.discord_status_online
"idle" -> R.drawable.discord_status_idle "idle" -> R.drawable.discord_status_idle
"dnd" -> R.drawable.discord_status_dnd "dnd" -> R.drawable.discord_status_dnd
else -> R.drawable.discord_status_online else -> R.drawable.discord_status_online
} }
imageSwitcher.setImageResource(initialStatus) settingsImageSwitcher.setImageResource(initialStatus)
val zoomInAnimation = val zoomInAnimation =
AnimationUtils.loadAnimation(this@SettingsActivity, R.anim.bounce_zoom) AnimationUtils.loadAnimation(this@SettingsActivity, R.anim.bounce_zoom)
imageSwitcher.setOnClickListener { settingsImageSwitcher.setOnClickListener {
var status = "online" var status = "online"
initialStatus = when (initialStatus) { initialStatus = when (initialStatus) {
R.drawable.discord_status_online -> { R.drawable.discord_status_online -> {
@ -292,11 +296,16 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
PrefManager.setVal(PrefName.DiscordStatus, status) PrefManager.setVal(PrefName.DiscordStatus, status)
imageSwitcher.setImageResource(initialStatus) settingsImageSwitcher.setImageResource(initialStatus)
imageSwitcher.startAnimation(zoomInAnimation) settingsImageSwitcher.startAnimation(zoomInAnimation)
}
settingsImageSwitcher.setOnLongClickListener {
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
DiscordDialogFragment().show(supportFragmentManager, "dialog")
true
} }
} else { } else {
imageSwitcher.visibility = View.GONE settingsImageSwitcher.visibility = View.GONE
settingsDiscordAvatar.setImageResource(R.drawable.ic_round_person_24) settingsDiscordAvatar.setImageResource(R.drawable.ic_round_person_24)
settingsDiscordUsername.visibility = View.GONE settingsDiscordUsername.visibility = View.GONE
settingsDiscordLogin.setText(R.string.login) settingsDiscordLogin.setText(R.string.login)

View file

@ -213,11 +213,10 @@
</LinearLayout> </LinearLayout>
<ImageView <ImageView
android:id="@+id/imageSwitcher" android:id="@+id/settingsImageSwitcher"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/discord_status_idle" android:src="@drawable/discord_status_idle"
android:onClick="onImageClicked"
android:padding="16dp" /> android:padding="16dp" />
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView

View file

@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bottom_sheet_background">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="32dp"
android:layout_height="4dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="14dp"
app:cardBackgroundColor="?attr/colorPrimary"
app:cardCornerRadius="2dp"
app:cardElevation="0dp" />
<TextView
android:id="@+id/bottomSheetCustomTitle"
android:layout_width="match_parent"
android:layout_height="48dp"
android:fontFamily="@font/poppins"
android:gravity="bottom|center_horizontal"
android:text="@string/discord_rich_presence"
android:textAlignment="center"
android:textSize="20sp"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/radio_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<RadioButton
android:id="@+id/radio_nothing"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="25dp"
android:fontFamily="@font/poppins_semi_bold"
android:text="@string/discord_nothing_button" />
<RadioButton
android:id="@+id/radio_dantotsu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_semi_bold"
android:text="@string/discord_dantotsu_button" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:id="@+id/dantotsuCard"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_gravity="center"
android:padding="8dp"
app:boxStrokeColor="@color/text_input_layout_stroke_color"
app:cardBackgroundColor="@color/nav_bg"
app:cardCornerRadius="16dp"
app:contentPadding="4dp"
app:contentPaddingLeft="8dp"
app:contentPaddingRight="8dp"
tools:ignore="ContentDescription,TextContrastCheck">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:drawablePadding="4dp"
android:fontFamily="@font/poppins_bold"
android:text="@string/stream_on_dantotsu"
android:textColor="?attr/colorPrimary"
app:drawableTint="?attr/colorPrimary" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:fontFamily="@font/poppins_bold"
android:text="@string/dantotsu"
android:textColor="?attr/colorPrimary"
app:drawableTint="?attr/colorPrimary" />
</LinearLayout>
<RadioButton
android:id="@+id/radio_anilist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_semi_bold"
android:text="@string/discord_anilist_button" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:id="@+id/anilistCard"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_gravity="center"
android:padding="8dp"
app:boxStrokeColor="@color/text_input_layout_stroke_color"
app:cardBackgroundColor="@color/nav_bg"
app:cardCornerRadius="16dp"
app:contentPadding="4dp"
app:contentPaddingLeft="8dp"
app:contentPaddingRight="8dp"
tools:ignore="ContentDescription,TextContrastCheck">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:drawablePadding="4dp"
android:fontFamily="@font/poppins_bold"
android:text="@string/view_my_anilist"
android:textColor="?attr/colorPrimary"
app:drawableTint="?attr/colorPrimary" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/anilistLinkPreview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:fontFamily="@font/poppins_bold"
android:text="@string/anilist_link"
android:textColor="?attr/colorPrimary"
app:drawableTint="?attr/colorPrimary" />
</LinearLayout>
</RadioGroup>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -2,9 +2,9 @@
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:background="@drawable/bottom_sheet_background"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:background="@drawable/bottom_sheet_background">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -21,7 +21,7 @@
android:layout_height="48dp" android:layout_height="48dp"
android:fontFamily="@font/poppins" android:fontFamily="@font/poppins"
android:gravity="bottom|center_horizontal" android:gravity="bottom|center_horizontal"
android:text="Liked By" android:text="@string/liked_by"
android:textSize="20sp" android:textSize="20sp"
android:textStyle="bold" /> android:textStyle="bold" />

View file

@ -9,10 +9,14 @@
<string name="login">Login</string> <string name="login">Login</string>
<string name="logout">Logout</string> <string name="logout">Logout</string>
<string name="dantotsu" translatable="false">https://dantotsu.app/</string>
<string name="discord" translatable="false">https://discord.gg/4HPZ5nAWwM</string> <string name="discord" translatable="false">https://discord.gg/4HPZ5nAWwM</string>
<string name="github" translatable="false">https://github.com/rebelonion/Dantotsu</string> <string name="github" translatable="false">https://github.com/rebelonion/Dantotsu</string>
<string name="telegram" translatable="false" tools:ignore="Typos">https://t.me/+gzBCQExtLQo1YTNh </string> <string name="telegram" translatable="false" tools:ignore="Typos">https://t.me/+gzBCQExtLQo1YTNh </string>
<string name="coffee" translatable="false">https://www.buymeacoffee.com/rebelonion</string> <string name="coffee" translatable="false">https://www.buymeacoffee.com/rebelonion</string>
<string name="anilist_link">https://anilist.co/user/%1$s/</string>
<string name="discord_link">https://discord.com/users/%1$s/</string>
<string name="home">Home</string> <string name="home">Home</string>
<string name="anime">Anime</string> <string name="anime">Anime</string>
@ -421,6 +425,13 @@
<string name="install_step">Step: %1$s</string> <string name="install_step">Step: %1$s</string>
<string name="review">Review</string> <string name="review">Review</string>
<string name="discord_nothing_button">Display only the first button</string>
<string name="discord_dantotsu_button">Display dantotsu in the second button</string>
<string name="discord_anilist_button">Display your AniList profile instead</string>
<string name="discord_rich_presence">Discord Rich Presence</string>
<string name="stream_on_dantotsu">Stream on Dantotsu</string>
<string name="view_my_anilist">View My AniList</string>
<string name="jobless_message">DAMN! YOU TRULY ARE JOBLESS\nYOU REACHED THE END</string> <string name="jobless_message">DAMN! YOU TRULY ARE JOBLESS\nYOU REACHED THE END</string>
<string name="file_manager_not_found">Couldn\'t find any File Manager to open SD card</string> <string name="file_manager_not_found">Couldn\'t find any File Manager to open SD card</string>
<string name="error_loading_data">Error loading data %1$s</string> <string name="error_loading_data">Error loading data %1$s</string>
@ -848,5 +859,6 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
<string name="top_rated">Top rated</string> <string name="top_rated">Top rated</string>
<string name="most_favourite">Most Favourite</string> <string name="most_favourite">Most Favourite</string>
<string name="trending_manhwa">Trending Manhwa</string> <string name="trending_manhwa">Trending Manhwa</string>
<string name="liked_by">Liked By</string>
<string name="adult_only_content">Adult only content</string> <string name="adult_only_content">Adult only content</string>
</resources> </resources>