mirror of
https://github.com/rebelonion/Dantotsu.git
synced 2026-01-27 22:01:02 +00:00
feat: front end for images
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package ani.dantotsu.connections.anilist
|
||||
|
||||
import android.net.Uri
|
||||
import ani.dantotsu.connections.anilist.Anilist.executeQuery
|
||||
import ani.dantotsu.connections.anilist.api.FuzzyDate
|
||||
import ani.dantotsu.connections.anilist.api.Query
|
||||
@@ -153,6 +154,36 @@ class AnilistMutations {
|
||||
return errors == null
|
||||
}
|
||||
|
||||
suspend fun uploadAvatar(avatarUri: Uri): Boolean {
|
||||
val query = """
|
||||
mutation (${"$"}avatar: Upload) {
|
||||
UpdateUser(
|
||||
avatar: ${"$"}avatar
|
||||
) {
|
||||
id
|
||||
}
|
||||
}
|
||||
"""
|
||||
val variables = mapOf("avatar" to avatarUri.toString())
|
||||
val result = executeQuery<JsonObject>(query, variables.toString())
|
||||
return result?.get("errors") == null && result != null
|
||||
}
|
||||
|
||||
suspend fun uploadBanner(bannerUri: Uri): Boolean {
|
||||
val query = """
|
||||
mutation (${"$"}banner: Upload) {
|
||||
UpdateUser(
|
||||
banner: ${"$"}banner
|
||||
) {
|
||||
id
|
||||
}
|
||||
}
|
||||
"""
|
||||
val variables = mapOf("banner" to bannerUri.toString())
|
||||
val result = executeQuery<JsonObject>(query, variables.toString())
|
||||
return result?.get("errors") == null && result != null
|
||||
}
|
||||
|
||||
|
||||
private fun String.stringSanitizer(): String {
|
||||
val sb = StringBuilder()
|
||||
|
||||
@@ -3,11 +3,13 @@ package ani.dantotsu.profile
|
||||
import android.animation.ObjectAnimator
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.PopupMenu
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isGone
|
||||
@@ -21,6 +23,7 @@ import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.anilist.AnilistMutations
|
||||
import ani.dantotsu.connections.anilist.api.Query
|
||||
import ani.dantotsu.databinding.ActivityProfileBinding
|
||||
import ani.dantotsu.databinding.ItemProfileAppBarBinding
|
||||
@@ -80,6 +83,8 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
|
||||
navBar.visibility = View.GONE
|
||||
binding.profileViewPager.isUserInputEnabled = false
|
||||
|
||||
bindingProfileAppBar = ItemProfileAppBarBinding.bind(binding.root)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val userid = intent.getIntExtra("userId", -1)
|
||||
val username = intent.getStringExtra("username") ?: ""
|
||||
@@ -117,6 +122,19 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
|
||||
|
||||
bindingProfileAppBar = ItemProfileAppBarBinding.bind(binding.root).apply {
|
||||
binding.profileProgressBar.visibility = View.GONE
|
||||
editProfileAvatar.visibility = View.GONE
|
||||
editProfileBanner.visibility = View.GONE
|
||||
|
||||
bindingProfileAppBar.editProfileAvatar.setOnClickListener {
|
||||
openMediaPickerForAvatar()
|
||||
}
|
||||
bindingProfileAppBar.editProfileBanner.setOnClickListener {
|
||||
openMediaPickerForBanner()
|
||||
}
|
||||
binding.apply {
|
||||
editProfileSave?.setOnClickListener { onSaveButtonClick() }
|
||||
}
|
||||
|
||||
followButton.isGone =
|
||||
user.id == Anilist.userid || Anilist.userid == null
|
||||
|
||||
@@ -149,14 +167,21 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
|
||||
profileMenuButton.setOnClickListener {
|
||||
val popup = PopupMenu(context, profileMenuButton)
|
||||
popup.menuInflater.inflate(R.menu.menu_profile, popup.menu)
|
||||
|
||||
if (user.id != Anilist.userid) {
|
||||
popup.menu.findItem(R.id.action_edit_profile)?.isVisible = false
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.action_view_on_anilist -> {
|
||||
openLinkInBrowser("https://anilist.co/user/${user.name}")
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
R.id.action_edit_profile -> {
|
||||
toggleEditProfile()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@@ -247,7 +272,84 @@ class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListene
|
||||
}
|
||||
}
|
||||
|
||||
//Collapsing UI Stuff
|
||||
private fun toggleEditProfile() {
|
||||
val viewIds = arrayOf(
|
||||
R.id.profileNavBar,
|
||||
R.id.profileButtonContainer,
|
||||
R.id.userStatsContainer,
|
||||
R.id.profileFavAnimeContainer,
|
||||
R.id.profileFavMangaContainer,
|
||||
R.id.profileFavCharactersContainer,
|
||||
//R.id.profileFavStaffContainer
|
||||
R.id.imageStatsContainer,
|
||||
R.id.editProfileAvatar,
|
||||
R.id.editProfileBanner,
|
||||
R.id.editProfileSave,
|
||||
)
|
||||
|
||||
viewIds.forEach { viewId ->
|
||||
findViewById<View>(viewId).apply {
|
||||
visibility = if (visibility == View.VISIBLE) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var avatarUri: Uri? = null
|
||||
private val avatarPicker =
|
||||
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
|
||||
uri?.let { avatarUri ->
|
||||
uploadAvatar(avatarUri)
|
||||
}
|
||||
}
|
||||
|
||||
private val bannerPicker =
|
||||
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
|
||||
uri?.let { bannerUri ->
|
||||
uploadBanner(bannerUri)
|
||||
}
|
||||
}
|
||||
|
||||
private fun openMediaPickerForAvatar() {
|
||||
avatarPicker.launch("image/*")
|
||||
}
|
||||
|
||||
private fun openMediaPickerForBanner() {
|
||||
bannerPicker.launch("image/*")
|
||||
}
|
||||
|
||||
private fun uploadAvatar(avatarUri: Uri) {
|
||||
this.avatarUri = avatarUri
|
||||
bindingProfileAppBar.profileUserAvatar.setImageURI(avatarUri)
|
||||
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val success = AnilistMutations().uploadAvatar(avatarUri)
|
||||
if (success) {
|
||||
toast("Avatar uploaded successfully")
|
||||
} else {
|
||||
toast("Failed to upload avatar")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
toast("Error uploading avatar: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun uploadBanner(bannerUri: Uri) {
|
||||
// Logic incoming
|
||||
bindingProfileAppBar.profileBannerImage.setImageURI(bannerUri)
|
||||
}
|
||||
|
||||
private fun onSaveButtonClick() {
|
||||
val currentAvatarUri = avatarUri
|
||||
if (currentAvatarUri != null) {
|
||||
uploadAvatar(currentAvatarUri)
|
||||
}
|
||||
toast("Uploading avatar and banner images...")
|
||||
}
|
||||
|
||||
|
||||
private var isCollapsed = false
|
||||
private val percent = 65
|
||||
private var mMaxScrollSize = 0
|
||||
|
||||
@@ -104,7 +104,7 @@ class ProfileFragment : Fragment() {
|
||||
}
|
||||
|
||||
binding.userInfoContainer.isVisible = user.about != null
|
||||
|
||||
binding.imageStatsContainer.visibility = View.GONE
|
||||
|
||||
binding.statsEpisodesWatched.text = user.statistics.anime.episodesWatched.toString()
|
||||
binding.statsDaysWatched.text =
|
||||
|
||||
@@ -35,6 +35,31 @@
|
||||
tools:ignore="SpeakableTextPresentCheck" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/editProfileSave"
|
||||
android:layout_width="122dp"
|
||||
android:layout_height="46dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="26dp"
|
||||
android:layout_marginBottom="46dp"
|
||||
android:backgroundTint="?attr/colorPrimary"
|
||||
android:baselineAligned="false"
|
||||
android:visibility="gone"
|
||||
app:cardCornerRadius="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/publish"
|
||||
android:layout_gravity="center_horizontal|center_vertical"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:textColor="?android:colorBackground"
|
||||
android:textSize="16sp">
|
||||
|
||||
</TextView>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<nl.joery.animatedbottombar.AnimatedBottomBar
|
||||
android:id="@+id/profileNavBar"
|
||||
|
||||
@@ -12,6 +12,69 @@
|
||||
android:nestedScrollingEnabled="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/imageStatsContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/avatarStatsTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Avatar"
|
||||
android:textSize="16sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/avatarStats"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Allowed Formats: JPEG, PNG. Max size: 3mb. Optimal dimensions: 230x230"
|
||||
android:alpha="0.58"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bannerStatsTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Banner"
|
||||
android:textSize="16sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/BannerStats"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Allowed Formats: JPEG, PNG. Max size: 6mb. Optimal dimensions: 1700x330"
|
||||
android:alpha="0.58"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/userStatsContainer"
|
||||
@@ -195,13 +258,24 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:ellipsize="end"
|
||||
android:nestedScrollingEnabled="true"
|
||||
android:padding="16dp"
|
||||
android:textAlignment="textStart"
|
||||
tools:text="@string/slogan" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/profileUserBioEditText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:textSize="16sp"
|
||||
android:background="@null"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="5"
|
||||
android:maxLines="10"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -45,6 +45,20 @@
|
||||
android:src="@drawable/linear_gradient_bg"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/editProfileBanner"
|
||||
android:layout_width="38dp"
|
||||
android:layout_height="38dp"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:contentDescription="@string/edit_profile"
|
||||
app:srcCompat="@drawable/ic_round_add_circle_24"
|
||||
tools:tint="@color/transparent"
|
||||
android:visibility="visible">
|
||||
</ImageView>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/profileUserDataContainer"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -53,25 +67,42 @@
|
||||
android:layout_marginBottom="8dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/profileUserAvatarContainer"
|
||||
android:layout_width="82dp"
|
||||
android:layout_height="82dp"
|
||||
android:layout_gravity="center"
|
||||
android:backgroundTint="@color/transparent"
|
||||
app:cardCornerRadius="64dp"
|
||||
app:strokeColor="@color/transparent">
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/profileUserAvatar"
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/profileUserAvatarContainer"
|
||||
android:layout_width="82dp"
|
||||
android:layout_height="82dp"
|
||||
android:layout_gravity="center"
|
||||
app:srcCompat="@drawable/ic_round_add_circle_24"
|
||||
tools:ignore="ContentDescription,ImageContrastCheck"
|
||||
tools:tint="@color/transparent" />
|
||||
android:backgroundTint="@color/transparent"
|
||||
app:cardCornerRadius="64dp"
|
||||
app:strokeColor="@color/transparent">
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/profileUserAvatar"
|
||||
android:layout_width="82dp"
|
||||
android:layout_height="82dp"
|
||||
android:layout_gravity="center"
|
||||
app:srcCompat="@drawable/ic_round_add_circle_24"
|
||||
tools:ignore="ContentDescription,ImageContrastCheck"
|
||||
tools:tint="@color/transparent" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/editProfileAvatar"
|
||||
android:layout_width="38dp"
|
||||
android:layout_height="38dp"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:contentDescription="@string/edit_profile"
|
||||
app:srcCompat="@drawable/ic_round_add_circle_24"
|
||||
tools:tint="@color/transparent"
|
||||
android:visibility="visible">
|
||||
</ImageView>
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profileUserName"
|
||||
|
||||
@@ -7,4 +7,9 @@
|
||||
android:title="@string/view_on_anilist"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit_profile"
|
||||
android:title="@string/edit_profile"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
||||
@@ -796,6 +796,7 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
||||
<string name="blur_banners">Blur Banners</string>
|
||||
<string name="blur">Blur</string>
|
||||
<string name="hide_scroll_bar">Hide Scroll Bar</string>
|
||||
<string name="edit_profile" translatable="false">Edit Profile</string>
|
||||
<string name="view_on_anilist" translatable="false">View on AniList</string>
|
||||
<string name="anilist_notification_filters">Filter Notifications</string>
|
||||
<string name="anilist_notifications_checking_time">Anilist notifications update frequency : %1$s</string>
|
||||
|
||||
Reference in New Issue
Block a user