Merge branch 'dev' of https://github.com/rebelonion/Dantotsu into dev
This commit is contained in:
commit
c22fd6b66d
78 changed files with 1982 additions and 1674 deletions
229
.github/workflows/beta.yml
vendored
229
.github/workflows/beta.yml
vendored
|
@ -12,6 +12,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CI: true
|
||||
SKIP_BUILD: false
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
|
@ -19,14 +20,12 @@ jobs:
|
|||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
- name: Download last SHA artifact
|
||||
uses: dawidd6/action-download-artifact@v3
|
||||
with:
|
||||
workflow: beta.yml
|
||||
name: last-sha
|
||||
path: .
|
||||
|
||||
continue-on-error: true
|
||||
|
||||
- name: Get Commits Since Last Run
|
||||
|
@ -39,7 +38,9 @@ jobs:
|
|||
fi
|
||||
echo "Commits since $LAST_SHA:"
|
||||
# Accumulate commit logs in a shell variable
|
||||
COMMIT_LOGS=$(git log $LAST_SHA..HEAD --pretty=format:"● %s ~%an")
|
||||
COMMIT_LOGS=$(git log $LAST_SHA..HEAD --pretty=format:"● %s ~%an [֍](https://github.com/${{ github.repository }}/commit/%H)")
|
||||
# Replace commit messages with pull request links
|
||||
COMMIT_LOGS=$(echo "$COMMIT_LOGS" | sed -E 's/#([0-9]+)/[#\1](https:\/\/github.com\/rebelonion\/Dantotsu\/pull\/\1)/g')
|
||||
# URL-encode the newline characters for GitHub Actions
|
||||
COMMIT_LOGS="${COMMIT_LOGS//'%'/'%25'}"
|
||||
COMMIT_LOGS="${COMMIT_LOGS//$'\n'/'%0A'}"
|
||||
|
@ -65,7 +66,11 @@ jobs:
|
|||
echo "Version $VERSION"
|
||||
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: List files in the directory
|
||||
run: ls -l
|
||||
|
||||
- name: Setup JDK 17
|
||||
if: ${{ env.SKIP_BUILD != 'true' }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
|
@ -73,18 +78,28 @@ jobs:
|
|||
cache: gradle
|
||||
|
||||
- name: Decode Keystore File
|
||||
if: ${{ github.repository == 'rebelonion/Dantotsu' }}
|
||||
run: echo "${{ secrets.KEYSTORE_FILE }}" | base64 -d > $GITHUB_WORKSPACE/key.keystore
|
||||
|
||||
- name: List files in the directory
|
||||
run: ls -l
|
||||
|
||||
- name: Make gradlew executable
|
||||
if: ${{ env.SKIP_BUILD != 'true' }}
|
||||
run: chmod +x ./gradlew
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew assembleGoogleAlpha -Pandroid.injected.signing.store.file=$GITHUB_WORKSPACE/key.keystore -Pandroid.injected.signing.store.password=${{ secrets.KEYSTORE_PASSWORD }} -Pandroid.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} -Pandroid.injected.signing.key.password=${{ secrets.KEY_PASSWORD }}
|
||||
if: ${{ env.SKIP_BUILD != 'true' }}
|
||||
run: |
|
||||
if [ "${{ github.repository }}" == "rebelonion/Dantotsu" ]; then
|
||||
./gradlew assembleGoogleAlpha \
|
||||
-Pandroid.injected.signing.store.file=$GITHUB_WORKSPACE/key.keystore \
|
||||
-Pandroid.injected.signing.store.password=${{ secrets.KEYSTORE_PASSWORD }} \
|
||||
-Pandroid.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} \
|
||||
-Pandroid.injected.signing.key.password=${{ secrets.KEY_PASSWORD }};
|
||||
else
|
||||
./gradlew assembleGoogleAlpha;
|
||||
fi
|
||||
|
||||
- name: Upload a Build Artifact
|
||||
if: ${{ env.SKIP_BUILD != 'true' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Dantotsu
|
||||
|
@ -93,24 +108,202 @@ jobs:
|
|||
path: "app/build/outputs/apk/google/alpha/app-google-alpha.apk"
|
||||
|
||||
- name: Upload APK to Discord and Telegram
|
||||
if: ${{ github.repository == 'rebelonion/Dantotsu' }}
|
||||
shell: bash
|
||||
run: |
|
||||
#Discord
|
||||
# Prepare Discord embed
|
||||
fetch_user_details() {
|
||||
local login=$1
|
||||
user_details=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"https://api.github.com/users/$login")
|
||||
name=$(echo "$user_details" | jq -r '.name // .login')
|
||||
login=$(echo "$user_details" | jq -r '.login')
|
||||
avatar_url=$(echo "$user_details" | jq -r '.avatar_url')
|
||||
echo "$name|$login|$avatar_url"
|
||||
}
|
||||
|
||||
# Additional information for the goats
|
||||
declare -A additional_info
|
||||
additional_info["ibo"]="\n Discord: <@951737931159187457>\n AniList: [takarealist112](<https://anilist.co/user/takarealist112/>)"
|
||||
additional_info["aayush262"]="\n Discord: <@918825160654598224>\n AniList: [aayush262](<https://anilist.co/user/aayush262/>)"
|
||||
additional_info["rebelonion"]="\n Discord: <@714249925248024617>\n AniList: [rebelonion](<https://anilist.co/user/rebelonion/>)\n PornHub: [rebelonion](<https://www.cornhub.com/model/rebelonion>)"
|
||||
|
||||
# Decimal color codes for contributors
|
||||
declare -A contributor_colors
|
||||
default_color="#ff25f9"
|
||||
contributor_colors["ibo"]="#ff7500"
|
||||
contributor_colors["aayush262"]="#5d689d"
|
||||
contributor_colors["Sadwhy"]="#ff7e95"
|
||||
contributor_colors["rebelonion"]="#d4e5ed"
|
||||
hex_to_decimal() { printf '%d' "0x${1#"#"}"; }
|
||||
|
||||
# Count recent commits and create an associative array
|
||||
declare -A recent_commit_counts
|
||||
while read -r count name; do
|
||||
recent_commit_counts["$name"]=$count
|
||||
done < <(echo "$COMMIT_LOG" | sed 's/%0A/\n/g' | grep -oP '(?<=~)[^[]*' | sort | uniq -c | sort -rn)
|
||||
# Fetch contributors from GitHub
|
||||
contributors=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"https://api.github.com/repos/${{ github.repository }}/contributors")
|
||||
|
||||
# Create a sorted list of contributors based on recent commit counts
|
||||
sorted_contributors=$(for login in $(echo "$contributors" | jq -r '.[].login'); do
|
||||
user_info=$(fetch_user_details "$login")
|
||||
name=$(echo "$user_info" | cut -d'|' -f1)
|
||||
count=${recent_commit_counts["$name"]:-0}
|
||||
echo "$count|$login"
|
||||
done | sort -rn | cut -d'|' -f2)
|
||||
|
||||
# Initialize needed variables
|
||||
developers=""
|
||||
committers_count=0
|
||||
max_commits=0
|
||||
top_contributor=""
|
||||
top_contributor_count=0
|
||||
top_contributor_avatar=""
|
||||
embed_color=$default_color
|
||||
|
||||
# Process contributors in the new order
|
||||
while read -r login; do
|
||||
user_info=$(fetch_user_details "$login")
|
||||
name=$(echo "$user_info" | cut -d'|' -f1)
|
||||
login=$(echo "$user_info" | cut -d'|' -f2)
|
||||
avatar_url=$(echo "$user_info" | cut -d'|' -f3)
|
||||
|
||||
# Only process if they have recent commits
|
||||
commit_count=${recent_commit_counts["$name"]:-0}
|
||||
if [ $commit_count -gt 0 ]; then
|
||||
# Update top contributor information
|
||||
if [ $commit_count -gt $max_commits ]; then
|
||||
max_commits=$commit_count
|
||||
top_contributors=("$login")
|
||||
top_contributor_count=1
|
||||
top_contributor_avatar="$avatar_url"
|
||||
embed_color=$(hex_to_decimal "${contributor_colors[$name]:-$default_color}")
|
||||
elif [ $commit_count -eq $max_commits ]; then
|
||||
top_contributors+=("$login")
|
||||
top_contributor_count=$((top_contributor_count + 1))
|
||||
embed_color=$default_color
|
||||
fi
|
||||
|
||||
# Get commit count for this contributor on the dev branch
|
||||
branch_commit_count=$(git rev-list --count dev --author="$login")
|
||||
|
||||
extra_info="${additional_info[$name]}"
|
||||
if [ -n "$extra_info" ]; then
|
||||
extra_info=$(echo "$extra_info" | sed 's/\\n/\n- /g')
|
||||
fi
|
||||
|
||||
# Construct the developer entry
|
||||
developer_entry="◗ **${name}** ${extra_info}
|
||||
- Github: [${login}](https://github.com/${login})
|
||||
- Commits: ${branch_commit_count}"
|
||||
|
||||
# Add the entry to developers, with a newline if it's not the first entry
|
||||
if [ -n "$developers" ]; then
|
||||
developers="${developers}
|
||||
${developer_entry}"
|
||||
else
|
||||
developers="${developer_entry}"
|
||||
fi
|
||||
committers_count=$((committers_count + 1))
|
||||
fi
|
||||
done <<< "$sorted_contributors"
|
||||
|
||||
# Set the thumbnail URL and color based on top contributor(s)
|
||||
if [ $top_contributor_count -eq 1 ]; then
|
||||
thumbnail_url="$top_contributor_avatar"
|
||||
else
|
||||
thumbnail_url="https://i.imgur.com/5o3Y9Jb.gif"
|
||||
embed_color=$default_color
|
||||
fi
|
||||
|
||||
# Truncate field values
|
||||
max_length=1000
|
||||
commit_messages=$(echo "$COMMIT_LOG" | sed 's/%0A/\n/g; s/^/\n/')
|
||||
# Truncate commit messages if they are too long
|
||||
max_length=1900 # Adjust this value as needed
|
||||
if [ ${#developers} -gt $max_length ]; then
|
||||
developers="${developers:0:$max_length}... (truncated)"
|
||||
fi
|
||||
if [ ${#commit_messages} -gt $max_length ]; then
|
||||
commit_messages="${commit_messages:0:$max_length}... (truncated)"
|
||||
fi
|
||||
contentbody=$( jq -nc --arg msg "Alpha-Build: <@&1225347048321191996> **$VERSION**:" --arg commits "$commit_messages" '{"content": ($msg + "\n" + $commits)}' )
|
||||
curl -F "payload_json=${contentbody}" -F "dantotsu_debug=@app/build/outputs/apk/google/alpha/app-google-alpha.apk" ${{ secrets.DISCORD_WEBHOOK }}
|
||||
|
||||
#Telegram
|
||||
curl -F "chat_id=${{ secrets.TELEGRAM_CHANNEL_ID }}" \
|
||||
-F "document=@app/build/outputs/apk/google/alpha/app-google-alpha.apk" \
|
||||
-F "caption=Alpha-Build: ${VERSION}: ${commit_messages}" \
|
||||
https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendDocument
|
||||
# Construct Discord payload
|
||||
discord_data=$(jq -nc \
|
||||
--arg field_value "$commit_messages" \
|
||||
--arg author_value "$developers" \
|
||||
--arg footer_text "Version $VERSION" \
|
||||
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \
|
||||
--arg thumbnail_url "$thumbnail_url" \
|
||||
--argjson embed_color "$embed_color" \
|
||||
'{
|
||||
"content": "<@&1225347048321191996>",
|
||||
"embeds": [
|
||||
{
|
||||
"title": "New Alpha-Build dropped",
|
||||
"color": $embed_color,
|
||||
"fields": [
|
||||
{
|
||||
"name": "Commits:",
|
||||
"value": $field_value,
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Developers:",
|
||||
"value": $author_value,
|
||||
"inline": false
|
||||
}
|
||||
],
|
||||
"footer": {
|
||||
"text": $footer_text
|
||||
},
|
||||
"timestamp": $timestamp,
|
||||
"thumbnail": {
|
||||
"url": $thumbnail_url
|
||||
}
|
||||
}
|
||||
],
|
||||
"attachments": []
|
||||
}')
|
||||
|
||||
# Send Discord message
|
||||
curl -H "Content-Type: application/json" \
|
||||
-d "$discord_data" \
|
||||
${{ secrets.DISCORD_WEBHOOK }}
|
||||
echo "You have only send an embed to discord due to SKIP_BUILD being set to true"
|
||||
|
||||
# Upload APK to Discord
|
||||
if [ "$SKIP_BUILD" != "true" ]; then
|
||||
curl -F "payload_json=${contentbody}" \
|
||||
-F "dantotsu_debug=@app/build/outputs/apk/google/alpha/app-google-alpha.apk" \
|
||||
${{ secrets.DISCORD_WEBHOOK }}
|
||||
else
|
||||
echo "Skipping APK upload to Discord due to SKIP_BUILD being set to true"
|
||||
fi
|
||||
|
||||
# Format commit messages for Telegram
|
||||
telegram_commit_messages=$(echo "$COMMIT_LOG" | sed 's/%0A/\n/g' | while read -r line; do
|
||||
message=$(echo "$line" | sed -E 's/● (.*) ~(.*) \[֍\]\((.*)\)/● \1 ~\2 <a href="\3">֍<\/a>/')
|
||||
message=$(echo "$message" | sed -E 's/\[#([0-9]+)\]\((https:\/\/github\.com\/[^)]+)\)/<a href="\2">#\1<\/a>/g')
|
||||
echo "$message"
|
||||
done)
|
||||
telegram_commit_messages="<blockquote>${telegram_commit_messages}</blockquote>"
|
||||
|
||||
# Upload APK to Telegram
|
||||
if [ "$SKIP_BUILD" != "true" ]; then
|
||||
APK_PATH="app/build/outputs/apk/google/alpha/app-google-alpha.apk"
|
||||
response=$(curl -sS -f -X POST \
|
||||
"https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendDocument" \
|
||||
-F "chat_id=${{ secrets.TELEGRAM_CHANNEL_ID }}" \
|
||||
-F "document=@$APK_PATH" \
|
||||
-F "caption=New Alpha-Build dropped 🔥
|
||||
|
||||
Commits:
|
||||
${telegram_commit_messages}
|
||||
version: ${VERSION}" \
|
||||
-F "parse_mode=HTML")
|
||||
else
|
||||
echo "Skipping Telegram message and APK upload due to SKIP_BUILD being set to true"
|
||||
fi
|
||||
|
||||
env:
|
||||
COMMIT_LOG: ${{ env.COMMIT_LOG }}
|
||||
|
|
|
@ -201,7 +201,7 @@
|
|||
android:name=".others.imagesearch.ImageSearchActivity"
|
||||
android:parentActivityName=".MainActivity" />
|
||||
<activity
|
||||
android:name=".util.MarkdownCreatorActivity"
|
||||
android:name=".util.ActivityMarkdownCreator"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity android:name=".parsers.ParserTestActivity" />
|
||||
<activity
|
||||
|
|
|
@ -854,7 +854,7 @@ fun savePrefsToDownloads(
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatMatches")
|
||||
fun savePrefs(serialized: String, path: String, title: String, context: Context): File? {
|
||||
var file = File(path, "$title.ani")
|
||||
var counter = 1
|
||||
|
@ -874,6 +874,7 @@ fun savePrefs(serialized: String, path: String, title: String, context: Context)
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatMatches")
|
||||
fun savePrefs(
|
||||
serialized: String,
|
||||
path: String,
|
||||
|
@ -920,7 +921,7 @@ fun shareImage(title: String, bitmap: Bitmap, context: Context) {
|
|||
intent.putExtra(Intent.EXTRA_STREAM, contentUri)
|
||||
context.startActivity(Intent.createChooser(intent, "Share $title"))
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatMatches")
|
||||
fun saveImage(image: Bitmap, path: String, imageFileName: String): File? {
|
||||
val imageFile = File(path, "$imageFileName.png")
|
||||
return try {
|
||||
|
@ -1500,7 +1501,6 @@ fun buildMarkwon(
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
|
|
|
@ -61,6 +61,7 @@ import ani.dantotsu.settings.saving.internal.PreferenceKeystore
|
|||
import ani.dantotsu.settings.saving.internal.PreferencePackager
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
@ -312,6 +313,7 @@ class MainActivity : AppCompatActivity() {
|
|||
mainViewPager.adapter =
|
||||
ViewPagerAdapter(supportFragmentManager, lifecycle)
|
||||
mainViewPager.setPageTransformer(ZoomOutPageTransformer())
|
||||
mainViewPager.offscreenPageLimit = 1
|
||||
navbar.selectTabAt(selectedOption)
|
||||
navbar.setOnTabSelectListener(object :
|
||||
AnimatedBottomBar.OnTabSelectListener {
|
||||
|
@ -493,35 +495,28 @@ class MainActivity : AppCompatActivity() {
|
|||
val password = CharArray(16).apply { fill('0') }
|
||||
|
||||
// Inflate the dialog layout
|
||||
val dialogView = DialogUserAgentBinding.inflate(layoutInflater)
|
||||
dialogView.userAgentTextBox.hint = "Password"
|
||||
dialogView.subtitle.visibility = View.VISIBLE
|
||||
dialogView.subtitle.text = getString(R.string.enter_password_to_decrypt_file)
|
||||
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("Enter Password")
|
||||
.setView(dialogView.root)
|
||||
.setPositiveButton("OK", null)
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
val dialogView = DialogUserAgentBinding.inflate(layoutInflater).apply {
|
||||
userAgentTextBox.hint = "Password"
|
||||
subtitle.visibility = View.VISIBLE
|
||||
subtitle.text = getString(R.string.enter_password_to_decrypt_file)
|
||||
}
|
||||
customAlertDialog().apply {
|
||||
setTitle("Enter Password")
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.yes) {
|
||||
val editText = dialogView.userAgentTextBox
|
||||
if (editText.text?.isNotBlank() == true) {
|
||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.cancel) {
|
||||
password.fill('0')
|
||||
dialog.dismiss()
|
||||
callback(null)
|
||||
}
|
||||
.create()
|
||||
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
|
||||
// Override the positive button here
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
val editText = dialog.findViewById<TextInputEditText>(R.id.userAgentTextBox)
|
||||
if (editText?.text?.isNotBlank() == true) {
|
||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||
dialog.dismiss()
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,30 +93,41 @@ class AnilistMutations {
|
|||
)
|
||||
}
|
||||
|
||||
suspend fun postActivity(text: String, edit : Int? = null): String {
|
||||
suspend fun postActivity(text: String, edit: Int? = null): String {
|
||||
val encodedText = text.stringSanitizer()
|
||||
val query = "mutation{SaveTextActivity(${if (edit != null) "id:$edit," else ""} text:$encodedText){siteUrl}}"
|
||||
val query =
|
||||
"mutation{SaveTextActivity(${if (edit != null) "id:$edit," else ""} text:$encodedText){siteUrl}}"
|
||||
val result = executeQuery<JsonObject>(query)
|
||||
val errors = result?.get("errors")
|
||||
return errors?.toString()
|
||||
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
||||
}
|
||||
suspend fun postMessage(userId: Int, text: String, edit: Int? = null,isPrivate: Boolean = false): String {
|
||||
val encodedText = text.replace("","").stringSanitizer()
|
||||
val query = "mutation{SaveMessageActivity(${if (edit != null) "id:$edit," else ""} recipientId:$userId,message:$encodedText,private:$isPrivate){id}}"
|
||||
|
||||
suspend fun postMessage(
|
||||
userId: Int,
|
||||
text: String,
|
||||
edit: Int? = null,
|
||||
isPrivate: Boolean = false
|
||||
): String {
|
||||
val encodedText = text.replace("", "").stringSanitizer()
|
||||
val query =
|
||||
"mutation{SaveMessageActivity(${if (edit != null) "id:$edit," else ""} recipientId:$userId,message:$encodedText,private:$isPrivate){id}}"
|
||||
val result = executeQuery<JsonObject>(query)
|
||||
val errors = result?.get("errors")
|
||||
return errors?.toString()
|
||||
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
||||
}
|
||||
suspend fun postReply(activityId: Int, text: String, edit: Int? = null ): String {
|
||||
|
||||
suspend fun postReply(activityId: Int, text: String, edit: Int? = null): String {
|
||||
val encodedText = text.stringSanitizer()
|
||||
val query = "mutation{SaveActivityReply(${if (edit != null) "id:$edit," else ""} activityId:$activityId,text:$encodedText){id}}"
|
||||
val query =
|
||||
"mutation{SaveActivityReply(${if (edit != null) "id:$edit," else ""} activityId:$activityId,text:$encodedText){id}}"
|
||||
val result = executeQuery<JsonObject>(query)
|
||||
val errors = result?.get("errors")
|
||||
return errors?.toString()
|
||||
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
||||
}
|
||||
|
||||
suspend fun postReview(summary: String, body: String, mediaId: Int, score: Int): String {
|
||||
val encodedSummary = summary.stringSanitizer()
|
||||
val encodedBody = body.stringSanitizer()
|
||||
|
@ -143,7 +154,6 @@ class AnilistMutations {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private fun String.stringSanitizer(): String {
|
||||
val sb = StringBuilder()
|
||||
var i = 0
|
||||
|
|
|
@ -479,6 +479,7 @@ class AnilistQueries {
|
|||
|
||||
suspend fun initHomePage(): Map<String, ArrayList<*>> {
|
||||
val removeList = PrefManager.getCustomVal("removeList", setOf<Int>())
|
||||
val hidePrivate = PrefManager.getVal<Boolean>(PrefName.HidePrivate)
|
||||
val removedMedia = ArrayList<Media>()
|
||||
val toShow: List<Boolean> =
|
||||
PrefManager.getVal(PrefName.HomeLayout) // anime continue, anime fav, anime planned, manga continue, manga fav, manga planned, recommendations
|
||||
|
@ -528,7 +529,7 @@ class AnilistQueries {
|
|||
current?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList) {
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
|
@ -540,7 +541,7 @@ class AnilistQueries {
|
|||
repeating?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList) {
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
|
@ -579,7 +580,7 @@ class AnilistQueries {
|
|||
current?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList) {
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
|
@ -612,7 +613,7 @@ class AnilistQueries {
|
|||
apiMediaList?.edges?.forEach {
|
||||
it.node?.let { i ->
|
||||
val m = Media(i).apply { isFav = true }
|
||||
if (m.id !in removeList) {
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
returnArray.add(m)
|
||||
} else {
|
||||
removedMedia.add(m)
|
||||
|
@ -1055,172 +1056,110 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult:
|
|||
return null
|
||||
}
|
||||
|
||||
private val onListAnime =
|
||||
(if (PrefManager.getVal(PrefName.IncludeAnimeList)) "" else "onList:false").replace(
|
||||
"\"",
|
||||
""
|
||||
)
|
||||
private val isAdult =
|
||||
(if (PrefManager.getVal(PrefName.AdultOnly)) "isAdult:true" else "").replace("\"", "")
|
||||
private fun mediaList(media1: Page?): ArrayList<Media> {
|
||||
val combinedList = arrayListOf<Media>()
|
||||
media1?.media?.mapTo(combinedList) { Media(it) }
|
||||
return combinedList
|
||||
}
|
||||
private fun getPreference(pref: PrefName): Boolean = PrefManager.getVal(pref)
|
||||
private fun buildQueryString(sort: String, type: String, format: String? = null, country: String? = null): String {
|
||||
val includeList = if (type == "ANIME" && !getPreference(PrefName.IncludeAnimeList)) "onList:false" else if (type == "MANGA" && !getPreference(PrefName.IncludeMangaList)) "onList:false" else ""
|
||||
val isAdult = if (getPreference(PrefName.AdultOnly)) "isAdult:true" else ""
|
||||
val formatFilter = format?.let { "format: $it, " } ?: ""
|
||||
val countryFilter = country?.let { "countryOfOrigin: $it, " } ?: ""
|
||||
|
||||
return """Page(page:1,perPage:50){
|
||||
pageInfo{hasNextPage total}
|
||||
media(sort:$sort, type:$type, $formatFilter $countryFilter $includeList $isAdult){
|
||||
id idMal status chapters episodes nextAiringEpisode{episode}
|
||||
isAdult type meanScore isFavourite format bannerImage countryOfOrigin
|
||||
coverImage{large} title{english romaji userPreferred}
|
||||
mediaListEntry{progress private score(format:POINT_100) status}
|
||||
}
|
||||
}"""
|
||||
}
|
||||
|
||||
private fun recentAnimeUpdates(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}airingSchedules(airingAt_greater:0 airingAt_lesser:${System.currentTimeMillis() / 1000 - 10000} sort:TIME_DESC){episode airingAt media{id idMal status chapters episodes nextAiringEpisode{episode} isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large} title{english romaji userPreferred} mediaListEntry{progress private score(format:POINT_100) status}}}}"""
|
||||
val currentTime = System.currentTimeMillis() / 1000
|
||||
return """Page(page:$page,perPage:50){
|
||||
pageInfo{hasNextPage total}
|
||||
airingSchedules(airingAt_greater:0 airingAt_lesser:${currentTime - 10000} sort:TIME_DESC){
|
||||
episode airingAt media{
|
||||
id idMal status chapters episodes nextAiringEpisode{episode}
|
||||
isAdult type meanScore isFavourite format bannerImage countryOfOrigin
|
||||
coverImage{large} title{english romaji userPreferred}
|
||||
mediaListEntry{progress private score(format:POINT_100) status}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
}
|
||||
|
||||
private fun trendingMovies(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:POPULARITY_DESC, type: ANIME, format: MOVIE, $onListAnime, $isAdult){id idMal status chapters episodes nextAiringEpisode{episode}isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}"""
|
||||
private fun queryAnimeList(): String {
|
||||
return """{
|
||||
recentUpdates:${recentAnimeUpdates(1)}
|
||||
recentUpdates2:${recentAnimeUpdates(2)}
|
||||
trendingMovies:${buildQueryString("POPULARITY_DESC", "ANIME", "MOVIE")}
|
||||
topRated:${buildQueryString("SCORE_DESC", "ANIME")}
|
||||
mostFav:${buildQueryString("FAVOURITES_DESC", "ANIME")}
|
||||
}"""
|
||||
}
|
||||
private fun queryMangaList(): String {
|
||||
return """{
|
||||
trendingManga:${buildQueryString("POPULARITY_DESC", "MANGA", country = "JP")}
|
||||
trendingManhwa:${buildQueryString("POPULARITY_DESC", "MANGA", country = "KR")}
|
||||
trendingNovel:${buildQueryString("POPULARITY_DESC", "MANGA", format = "NOVEL", country = "JP")}
|
||||
topRated:${buildQueryString("SCORE_DESC", "MANGA")}
|
||||
mostFav:${buildQueryString("FAVOURITES_DESC", "MANGA")}
|
||||
|
||||
private fun topRatedAnime(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort: SCORE_DESC, type: ANIME, $onListAnime, $isAdult){id idMal status chapters episodes nextAiringEpisode{episode}isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}"""
|
||||
}
|
||||
|
||||
private fun mostFavAnime(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:FAVOURITES_DESC,type: ANIME, $onListAnime, $isAdult){id idMal status chapters episodes nextAiringEpisode{episode}isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}"""
|
||||
}"""
|
||||
}
|
||||
|
||||
suspend fun loadAnimeList(): Map<String, ArrayList<Media>> {
|
||||
val list = mutableMapOf<String, ArrayList<Media>>()
|
||||
fun query(): String {
|
||||
return """{
|
||||
recentUpdates:${recentAnimeUpdates(1)}
|
||||
recentUpdates2:${recentAnimeUpdates(2)}
|
||||
trendingMovies:${trendingMovies(1)}
|
||||
trendingMovies2:${trendingMovies(2)}
|
||||
topRated:${topRatedAnime(1)}
|
||||
topRated2:${topRatedAnime(2)}
|
||||
mostFav:${mostFavAnime(1)}
|
||||
mostFav2:${mostFavAnime(2)}
|
||||
}""".trimIndent()
|
||||
}
|
||||
executeQuery<Query.AnimeList>(query(), force = true)?.data?.apply {
|
||||
|
||||
fun filterRecentUpdates(
|
||||
page: Page?,
|
||||
): ArrayList<Media> {
|
||||
val listOnly: Boolean = PrefManager.getVal(PrefName.RecentlyListOnly)
|
||||
val adultOnly: Boolean = PrefManager.getVal(PrefName.AdultOnly)
|
||||
val idArr = mutableListOf<Int>()
|
||||
list["recentUpdates"] = recentUpdates?.airingSchedules?.mapNotNull { i ->
|
||||
return page?.airingSchedules?.mapNotNull { i ->
|
||||
i.media?.let {
|
||||
if (!idArr.contains(it.id))
|
||||
if (!listOnly && it.countryOfOrigin == "JP" && Anilist.adult && adultOnly && it.isAdult == true) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else if (!listOnly && !adultOnly && (it.countryOfOrigin == "JP" && it.isAdult == false)) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else if ((listOnly && it.mediaListEntry != null)) {
|
||||
if (!idArr.contains(it.id)) {
|
||||
val shouldAdd = when {
|
||||
!listOnly && it.countryOfOrigin == "JP" && Anilist.adult && adultOnly && it.isAdult == true -> true
|
||||
!listOnly && !adultOnly && it.countryOfOrigin == "JP" && it.isAdult == false -> true
|
||||
listOnly && it.mediaListEntry != null -> true
|
||||
else -> false
|
||||
}
|
||||
if (shouldAdd) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else null
|
||||
else null
|
||||
} else null
|
||||
}
|
||||
}?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
|
||||
list["trendingMovies"] =
|
||||
trendingMovies?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["topRated"] =
|
||||
topRated?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["mostFav"] =
|
||||
mostFav?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
|
||||
list["recentUpdates"]?.addAll(recentUpdates2?.airingSchedules?.mapNotNull { i ->
|
||||
i.media?.let {
|
||||
if (!idArr.contains(it.id))
|
||||
if (!listOnly && it.countryOfOrigin == "JP" && Anilist.adult && adultOnly && it.isAdult == true) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else if (!listOnly && !adultOnly && (it.countryOfOrigin == "JP" && it.isAdult == false)) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else if ((listOnly && it.mediaListEntry != null)) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else null
|
||||
else null
|
||||
}
|
||||
}?.toCollection(ArrayList()) ?: arrayListOf())
|
||||
list["trendingMovies"]?.addAll(trendingMovies2?.media?.map { Media(it) }
|
||||
?.toCollection(ArrayList()) ?: arrayListOf())
|
||||
list["topRated"]?.addAll(
|
||||
topRated2?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
)
|
||||
list["mostFav"]?.addAll(
|
||||
mostFav2?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
)
|
||||
}
|
||||
executeQuery<Query.AnimeList>(queryAnimeList(), force = true)?.data?.apply {
|
||||
list["recentUpdates"] = filterRecentUpdates(recentUpdates)
|
||||
list["trendingMovies"] = mediaList(trendingMovies)
|
||||
list["topRated"] = mediaList(topRated)
|
||||
list["mostFav"] = mediaList(mostFav)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
private val onListManga =
|
||||
(if (PrefManager.getVal(PrefName.IncludeMangaList)) "" else "onList:false").replace(
|
||||
"\"",
|
||||
""
|
||||
)
|
||||
|
||||
private fun trendingManga(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:POPULARITY_DESC, type: MANGA,countryOfOrigin:JP, $onListManga, $isAdult){id idMal status chapters episodes nextAiringEpisode{episode}isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}"""
|
||||
}
|
||||
|
||||
private fun trendingManhwa(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:POPULARITY_DESC, type: MANGA, countryOfOrigin:KR, $onListManga, $isAdult){id idMal status chapters episodes nextAiringEpisode{episode}isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}"""
|
||||
}
|
||||
|
||||
private fun trendingNovel(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:POPULARITY_DESC, type: MANGA, format: NOVEL, countryOfOrigin:JP, $onListManga, $isAdult){id idMal status chapters episodes nextAiringEpisode{episode}isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}"""
|
||||
}
|
||||
|
||||
private fun topRatedManga(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort: SCORE_DESC, type: MANGA, $onListManga, $isAdult){id idMal status chapters episodes nextAiringEpisode{episode}isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}"""
|
||||
}
|
||||
|
||||
private fun mostFavManga(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:FAVOURITES_DESC,type: MANGA, $onListManga, $isAdult){id idMal status chapters episodes nextAiringEpisode{episode}isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}"""
|
||||
}
|
||||
|
||||
suspend fun loadMangaList(): Map<String, ArrayList<Media>> {
|
||||
val list = mutableMapOf<String, ArrayList<Media>>()
|
||||
fun query(): String {
|
||||
return """{
|
||||
trendingManga:${trendingManga(1)}
|
||||
trendingManga2:${trendingManga(2)}
|
||||
trendingManhwa:${trendingManhwa(1)}
|
||||
trendingManhwa2:${trendingManhwa(2)}
|
||||
trendingNovel:${trendingNovel(1)}
|
||||
trendingNovel2:${trendingNovel(2)}
|
||||
topRated:${topRatedManga(1)}
|
||||
topRated2:${topRatedManga(2)}
|
||||
mostFav:${mostFavManga(1)}
|
||||
mostFav2:${mostFavManga(2)}
|
||||
}""".trimIndent()
|
||||
executeQuery<Query.MangaList>(queryMangaList(), force = true)?.data?.apply {
|
||||
list["trendingManga"] = mediaList(trendingManga)
|
||||
list["trendingManhwa"] = mediaList(trendingManhwa)
|
||||
list["trendingNovel"] = mediaList(trendingNovel)
|
||||
list["topRated"] = mediaList(topRated)
|
||||
list["mostFav"] = mediaList(mostFav)
|
||||
}
|
||||
|
||||
executeQuery<Query.MangaList>(query(), force = true)?.data?.apply {
|
||||
list["trendingManga"] =
|
||||
trendingManga?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["trendingManhwa"] =
|
||||
trendingManhwa?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["trendingNovel"] =
|
||||
trendingNovel?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["topRated"] =
|
||||
topRated?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["mostFav"] =
|
||||
mostFav?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
|
||||
list["trendingManga"]?.addAll(
|
||||
trendingManga2?.media?.map { Media(it) }?.toList() ?: arrayListOf()
|
||||
)
|
||||
list["trendingManhwa"]?.addAll(
|
||||
trendingManhwa2?.media?.map { Media(it) }?.toList() ?: arrayListOf()
|
||||
)
|
||||
list["trendingNovel"]?.addAll(
|
||||
trendingNovel2?.media?.map { Media(it) }?.toList() ?: arrayListOf()
|
||||
)
|
||||
list["topRated"]?.addAll(topRated2?.media?.map { Media(it) }?.toList() ?: arrayListOf())
|
||||
list["mostFav"]?.addAll(mostFav2?.media?.map { Media(it) }?.toList() ?: arrayListOf())
|
||||
}
|
||||
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
|
||||
suspend fun recentlyUpdated(
|
||||
greater: Long = 0,
|
||||
lesser: Long = System.currentTimeMillis() / 1000 - 10000
|
||||
|
|
|
@ -163,13 +163,9 @@ class Query {
|
|||
@Serializable
|
||||
data class Data(
|
||||
@SerialName("recentUpdates") val recentUpdates: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("recentUpdates2") val recentUpdates2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingMovies") val trendingMovies: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingMovies2") val trendingMovies2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("topRated") val topRated: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("topRated2") val topRated2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("mostFav") val mostFav: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("mostFav2") val mostFav2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -181,15 +177,10 @@ class Query {
|
|||
@Serializable
|
||||
data class Data(
|
||||
@SerialName("trendingManga") val trendingManga: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingManga2") val trendingManga2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingManhwa") val trendingManhwa: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingManhwa2") val trendingManhwa2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingNovel") val trendingNovel: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingNovel2") val trendingNovel2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("topRated") val topRated: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("topRated2") val topRated2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("mostFav") val mostFav: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("mostFav2") val mostFav2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.anggrayudi.storage.file.openInputStream
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
|
@ -203,25 +204,22 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
val type: MediaType = MediaType.ANIME
|
||||
|
||||
// Alert dialog to confirm deletion
|
||||
val builder =
|
||||
androidx.appcompat.app.AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
builder.setTitle("Delete ${item.title}?")
|
||||
builder.setMessage("Are you sure you want to delete ${item.title}?")
|
||||
builder.setPositiveButton("Yes") { _, _ ->
|
||||
downloadManager.removeMedia(item.title, type)
|
||||
val mediaIds =
|
||||
PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values
|
||||
?: emptySet()
|
||||
if (mediaIds.isEmpty()) {
|
||||
snackString("No media found") // if this happens, terrible things have happened
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Delete ${item.title}?")
|
||||
setMessage("Are you sure you want to delete ${item.title}?")
|
||||
setPosButton(R.string.yes) {
|
||||
downloadManager.removeMedia(item.title, type)
|
||||
val mediaIds = PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values ?: emptySet()
|
||||
if (mediaIds.isEmpty()) {
|
||||
snackString("No media found") // if this happens, terrible things have happened
|
||||
}
|
||||
getDownloads()
|
||||
}
|
||||
getDownloads()
|
||||
setNegButton(R.string.no) {
|
||||
// Do nothing
|
||||
}
|
||||
show()
|
||||
}
|
||||
builder.setNegativeButton("No") { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.anggrayudi.storage.file.openInputStream
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
|
@ -201,19 +202,15 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
MediaType.NOVEL
|
||||
}
|
||||
// Alert dialog to confirm deletion
|
||||
val builder =
|
||||
androidx.appcompat.app.AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
builder.setTitle("Delete ${item.title}?")
|
||||
builder.setMessage("Are you sure you want to delete ${item.title}?")
|
||||
builder.setPositiveButton("Yes") { _, _ ->
|
||||
downloadManager.removeMedia(item.title, type)
|
||||
getDownloads()
|
||||
}
|
||||
builder.setNegativeButton("No") { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Delete ${item.title}?")
|
||||
setMessage("Are you sure you want to delete ${item.title}?")
|
||||
setPosButton(R.string.yes) {
|
||||
downloadManager.removeMedia(item.title, type)
|
||||
getDownloads()
|
||||
}
|
||||
setNegButton(R.string.no)
|
||||
}.show()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package ani.dantotsu.download.video
|
|||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
|
@ -29,10 +28,10 @@ import ani.dantotsu.download.anime.AnimeDownloaderService
|
|||
import ani.dantotsu.download.anime.AnimeServiceDataSingleton
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.parsers.Subtitle
|
||||
import ani.dantotsu.parsers.Video
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
@ -72,19 +71,19 @@ object Helper {
|
|||
episodeImage
|
||||
)
|
||||
|
||||
val downloadsManger = Injekt.get<DownloadsManager>()
|
||||
val downloadCheck = downloadsManger
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
val downloadCheck = downloadsManager
|
||||
.queryDownload(title, episode, MediaType.ANIME)
|
||||
|
||||
if (downloadCheck) {
|
||||
AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle("Download Exists")
|
||||
.setMessage("A download for this episode already exists. Do you want to overwrite it?")
|
||||
.setPositiveButton("Yes") { _, _ ->
|
||||
context.customAlertDialog().apply {
|
||||
setTitle("Download Exists")
|
||||
setMessage("A download for this episode already exists. Do you want to overwrite it?")
|
||||
setPosButton(R.string.yes) {
|
||||
PrefManager.getAnimeDownloadPreferences().edit()
|
||||
.remove(animeDownloadTask.getTaskName())
|
||||
.apply()
|
||||
downloadsManger.removeDownload(
|
||||
downloadsManager.removeDownload(
|
||||
DownloadedType(
|
||||
title,
|
||||
episode,
|
||||
|
@ -99,8 +98,9 @@ object Helper {
|
|||
}
|
||||
}
|
||||
}
|
||||
.setNegativeButton("No") { _, _ -> }
|
||||
.show()
|
||||
setNegButton(R.string.no)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
AnimeServiceDataSingleton.downloadQueue.offer(animeDownloadTask)
|
||||
if (!AnimeServiceDataSingleton.isServiceRunning) {
|
||||
|
|
|
@ -482,13 +482,12 @@ class HomeFragment : Fragment() {
|
|||
CoroutineScope(Dispatchers.IO).launch {
|
||||
model.setListImages()
|
||||
}
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
model.initUserStatus()
|
||||
}
|
||||
|
||||
var empty = true
|
||||
val homeLayoutShow: List<Boolean> =
|
||||
PrefManager.getVal(PrefName.HomeLayout)
|
||||
model.initHomePage()
|
||||
model.initUserStatus()
|
||||
(array.indices).forEach { i ->
|
||||
if (homeLayoutShow.elementAt(i)) {
|
||||
empty = false
|
||||
|
|
|
@ -12,12 +12,14 @@ import androidx.documentfile.provider.DocumentFile
|
|||
import androidx.fragment.app.Fragment
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.databinding.DialogUserAgentBinding
|
||||
import ani.dantotsu.databinding.FragmentLoginBinding
|
||||
import ani.dantotsu.openLinkInBrowser
|
||||
import ani.dantotsu.settings.saving.internal.PreferenceKeystore
|
||||
import ani.dantotsu.settings.saving.internal.PreferencePackager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
class LoginFragment : Fragment() {
|
||||
|
@ -94,38 +96,31 @@ class LoginFragment : Fragment() {
|
|||
val password = CharArray(16).apply { fill('0') }
|
||||
|
||||
// Inflate the dialog layout
|
||||
val dialogView =
|
||||
LayoutInflater.from(requireActivity()).inflate(R.layout.dialog_user_agent, null)
|
||||
dialogView.findViewById<TextInputEditText>(R.id.userAgentTextBox)?.hint = "Password"
|
||||
val subtitleTextView = dialogView.findViewById<TextView>(R.id.subtitle)
|
||||
subtitleTextView?.visibility = View.VISIBLE
|
||||
subtitleTextView?.text = "Enter your password to decrypt the file"
|
||||
val dialogView = DialogUserAgentBinding.inflate(layoutInflater).apply {
|
||||
userAgentTextBox.hint = "Password"
|
||||
subtitle.visibility = View.VISIBLE
|
||||
subtitle.text = getString(R.string.enter_password_to_decrypt_file)
|
||||
}
|
||||
|
||||
val dialog = AlertDialog.Builder(requireActivity(), R.style.MyPopup)
|
||||
.setTitle("Enter Password")
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK", null)
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
requireActivity().customAlertDialog().apply {
|
||||
setTitle("Enter Password")
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.ok){
|
||||
val editText = dialogView.userAgentTextBox
|
||||
if (editText.text?.isNotBlank() == true) {
|
||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.cancel) {
|
||||
password.fill('0')
|
||||
dialog.dismiss()
|
||||
callback(null)
|
||||
}
|
||||
.create()
|
||||
}.show()
|
||||
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
|
||||
// Override the positive button here
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
val editText = dialog.findViewById<TextInputEditText>(R.id.userAgentTextBox)
|
||||
if (editText?.text?.isNotBlank() == true) {
|
||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||
dialog.dismiss()
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun restartApp() {
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
|
@ -16,7 +15,6 @@ import androidx.core.app.ActivityOptionsCompat
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
|
@ -32,6 +30,7 @@ import ani.dantotsu.profile.ProfileActivity
|
|||
import ani.dantotsu.profile.User
|
||||
import ani.dantotsu.profile.UsersDialogFragment
|
||||
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
||||
import ani.dantotsu.profile.activity.RepliesBottomDialog
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ani.dantotsu.home.status
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
|
@ -16,7 +15,7 @@ import ani.dantotsu.profile.User
|
|||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
|
||||
class UserStatusAdapter(private val user: ArrayList<User>) :
|
||||
RecyclerView.Adapter<UserStatusAdapter.UsersViewHolder>() {
|
||||
|
@ -43,7 +42,7 @@ class UserStatusAdapter(private val user: ArrayList<User>) :
|
|||
if (user[bindingAdapterPosition].id == Anilist.userid) {
|
||||
ContextCompat.startActivity(
|
||||
itemView.context,
|
||||
Intent(itemView.context, MarkdownCreatorActivity::class.java)
|
||||
Intent(itemView.context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "activity"),
|
||||
null
|
||||
)
|
||||
|
|
|
@ -30,6 +30,7 @@ class CalendarActivity : AppCompatActivity() {
|
|||
private lateinit var binding: ActivityListBinding
|
||||
private val scope = lifecycleScope
|
||||
private var selectedTabIdx = 1
|
||||
private var showOnlyLibrary = false
|
||||
private val model: OtherDetailsViewModel by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -38,8 +39,6 @@ class CalendarActivity : AppCompatActivity() {
|
|||
ThemeManager(this).applyTheme()
|
||||
binding = ActivityListBinding.inflate(layoutInflater)
|
||||
|
||||
|
||||
|
||||
val primaryColor = getThemeColor(com.google.android.material.R.attr.colorSurface)
|
||||
val primaryTextColor = getThemeColor(com.google.android.material.R.attr.colorPrimary)
|
||||
val secondaryTextColor = getThemeColor(com.google.android.material.R.attr.colorOutline)
|
||||
|
@ -79,6 +78,17 @@ class CalendarActivity : AppCompatActivity() {
|
|||
override fun onTabReselected(tab: TabLayout.Tab?) {}
|
||||
})
|
||||
|
||||
binding.listed.setOnClickListener {
|
||||
showOnlyLibrary = !showOnlyLibrary
|
||||
binding.listed.setImageResource(
|
||||
if (showOnlyLibrary) R.drawable.ic_round_collections_bookmark_24
|
||||
else R.drawable.ic_round_library_books_24
|
||||
)
|
||||
scope.launch {
|
||||
model.loadCalendar(showOnlyLibrary)
|
||||
}
|
||||
}
|
||||
|
||||
model.getCalendar().observe(this) {
|
||||
if (it != null) {
|
||||
binding.listProgressBar.visibility = View.GONE
|
||||
|
@ -97,11 +107,10 @@ class CalendarActivity : AppCompatActivity() {
|
|||
live.observe(this) {
|
||||
if (it) {
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) { model.loadCalendar() }
|
||||
withContext(Dispatchers.IO) { model.loadCalendar(showOnlyLibrary) }
|
||||
live.postValue(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,25 +26,50 @@ class OtherDetailsViewModel : ViewModel() {
|
|||
if (author.value == null) author.postValue(Anilist.query.getAuthorDetails(m))
|
||||
}
|
||||
|
||||
private var cachedAllCalendarData: Map<String, MutableList<Media>>? = null
|
||||
private var cachedLibraryCalendarData: Map<String, MutableList<Media>>? = null
|
||||
private val calendar: MutableLiveData<Map<String, MutableList<Media>>> = MutableLiveData(null)
|
||||
fun getCalendar(): LiveData<Map<String, MutableList<Media>>> = calendar
|
||||
suspend fun loadCalendar() {
|
||||
val curr = System.currentTimeMillis() / 1000
|
||||
val res = Anilist.query.recentlyUpdated(curr - 86400, curr + (86400 * 6))
|
||||
val df = DateFormat.getDateInstance(DateFormat.FULL)
|
||||
val map = mutableMapOf<String, MutableList<Media>>()
|
||||
val idMap = mutableMapOf<String, MutableList<Int>>()
|
||||
res?.forEach {
|
||||
val v = it.relation?.split(",")?.map { i -> i.toLong() }!!
|
||||
val dateInfo = df.format(Date(v[1] * 1000))
|
||||
val list = map.getOrPut(dateInfo) { mutableListOf() }
|
||||
val idList = idMap.getOrPut(dateInfo) { mutableListOf() }
|
||||
it.relation = "Episode ${v[0]}"
|
||||
if (!idList.contains(it.id)) {
|
||||
idList.add(it.id)
|
||||
list.add(it)
|
||||
suspend fun loadCalendar(showOnlyLibrary: Boolean = false) {
|
||||
if (cachedAllCalendarData == null || cachedLibraryCalendarData == null) {
|
||||
val curr = System.currentTimeMillis() / 1000
|
||||
val res = Anilist.query.recentlyUpdated(curr - 86400, curr + (86400 * 6))
|
||||
val df = DateFormat.getDateInstance(DateFormat.FULL)
|
||||
val allMap = mutableMapOf<String, MutableList<Media>>()
|
||||
val libraryMap = mutableMapOf<String, MutableList<Media>>()
|
||||
val idMap = mutableMapOf<String, MutableList<Int>>()
|
||||
|
||||
val userId = Anilist.userid ?: 0
|
||||
val userLibrary = Anilist.query.getMediaLists(true, userId)
|
||||
val libraryMediaIds = userLibrary.flatMap { it.value }.map { it.id }
|
||||
|
||||
res.forEach {
|
||||
val v = it.relation?.split(",")?.map { i -> i.toLong() }!!
|
||||
val dateInfo = df.format(Date(v[1] * 1000))
|
||||
val list = allMap.getOrPut(dateInfo) { mutableListOf() }
|
||||
val libraryList = if (libraryMediaIds.contains(it.id)) {
|
||||
libraryMap.getOrPut(dateInfo) { mutableListOf() }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val idList = idMap.getOrPut(dateInfo) { mutableListOf() }
|
||||
it.relation = "Episode ${v[0]}"
|
||||
if (!idList.contains(it.id)) {
|
||||
idList.add(it.id)
|
||||
list.add(it)
|
||||
libraryList?.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
cachedAllCalendarData = allMap
|
||||
cachedLibraryCalendarData = libraryMap
|
||||
}
|
||||
calendar.postValue(map)
|
||||
|
||||
val cacheToUse: Map<String, MutableList<Media>> = if (showOnlyLibrary) {
|
||||
cachedLibraryCalendarData ?: emptyMap()
|
||||
} else {
|
||||
cachedAllCalendarData ?: emptyMap()
|
||||
}
|
||||
calendar.postValue(cacheToUse)
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package ani.dantotsu.media
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableString
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -21,7 +20,7 @@ import ani.dantotsu.initActivity
|
|||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -59,7 +58,7 @@ class ReviewActivity : AppCompatActivity() {
|
|||
binding.followFilterButton.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
this,
|
||||
Intent(this, MarkdownCreatorActivity::class.java)
|
||||
Intent(this, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "review"),
|
||||
null
|
||||
)
|
||||
|
|
|
@ -183,6 +183,12 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
binding.searchByImage.setOnClickListener {
|
||||
activity.startActivity(Intent(activity, ImageSearchActivity::class.java))
|
||||
}
|
||||
binding.clearHistory.setOnClickListener {
|
||||
it.startAnimation(fadeOutAnimation())
|
||||
it.visibility = View.GONE
|
||||
searchHistoryAdapter.clearHistory()
|
||||
}
|
||||
updateClearHistoryVisibility()
|
||||
fun searchTitle() {
|
||||
activity.result.apply {
|
||||
search =
|
||||
|
@ -300,11 +306,17 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
}
|
||||
|
||||
binding.searchResultLayout.visibility = View.VISIBLE
|
||||
binding.clearHistory.visibility = View.GONE
|
||||
binding.searchHistoryList.visibility = View.GONE
|
||||
binding.searchByImage.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateClearHistoryVisibility() {
|
||||
binding.clearHistory.visibility =
|
||||
if (searchHistoryAdapter.itemCount > 0) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun fadeInAnimation(): Animation {
|
||||
return AlphaAnimation(0f, 1f).apply {
|
||||
duration = 150
|
||||
|
@ -375,4 +387,3 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
override fun getItemCount(): Int = chips.size
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,12 @@ class SearchHistoryAdapter(private val type: String, private val searchClicked:
|
|||
PrefManager.setVal(historyType, searchHistory)
|
||||
}
|
||||
|
||||
fun clearHistory() {
|
||||
searchHistory?.clear()
|
||||
PrefManager.setVal(historyType, searchHistory)
|
||||
submitList(searchHistory?.toList())
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
|
|
|
@ -8,7 +8,6 @@ import android.view.ViewGroup
|
|||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.core.view.isGone
|
||||
|
@ -19,7 +18,7 @@ import ani.dantotsu.FileUrl
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.databinding.DialogLayoutBinding
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemMediaSourceBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.displayTimer
|
||||
import ani.dantotsu.isOnline
|
||||
|
@ -33,12 +32,14 @@ import ani.dantotsu.others.LanguageMapper
|
|||
import ani.dantotsu.others.webview.CookieCatcher
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.DynamicAnimeParser
|
||||
import ani.dantotsu.parsers.OfflineAnimeParser
|
||||
import ani.dantotsu.parsers.WatchSources
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.FAQActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.chip.Chip
|
||||
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK
|
||||
|
@ -54,16 +55,13 @@ class AnimeWatchAdapter(
|
|||
) : RecyclerView.Adapter<AnimeWatchAdapter.ViewHolder>() {
|
||||
private var autoSelect = true
|
||||
var subscribe: MediaDetailsActivity.PopImageButton? = null
|
||||
private var _binding: ItemAnimeWatchBinding? = null
|
||||
private var _binding: ItemMediaSourceBinding? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val bind = ItemAnimeWatchBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val bind = ItemMediaSourceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(bind)
|
||||
}
|
||||
|
||||
private var nestedDialog: AlertDialog? = null
|
||||
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
_binding = binding
|
||||
|
@ -75,7 +73,7 @@ class AnimeWatchAdapter(
|
|||
null
|
||||
)
|
||||
}
|
||||
//Youtube
|
||||
// Youtube
|
||||
if (media.anime?.youtube != null && PrefManager.getVal(PrefName.ShowYtButton)) {
|
||||
binding.animeSourceYT.visibility = View.VISIBLE
|
||||
binding.animeSourceYT.setOnClickListener {
|
||||
|
@ -89,7 +87,7 @@ class AnimeWatchAdapter(
|
|||
R.string.subbed
|
||||
)
|
||||
|
||||
//PreferDub
|
||||
// PreferDub
|
||||
var changing = false
|
||||
binding.animeSourceDubbed.setOnCheckedChangeListener { _, isChecked ->
|
||||
binding.animeSourceDubbedText.text =
|
||||
|
@ -99,8 +97,8 @@ class AnimeWatchAdapter(
|
|||
if (!changing) fragment.onDubClicked(isChecked)
|
||||
}
|
||||
|
||||
//Wrong Title
|
||||
binding.animeSourceSearch.setOnClickListener {
|
||||
// Wrong Title
|
||||
binding.mediaSourceSearch.setOnClickListener {
|
||||
SourceSearchDialogFragment().show(
|
||||
fragment.requireActivity().supportFragmentManager,
|
||||
null
|
||||
|
@ -108,37 +106,37 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
val offline = !isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||
|
||||
binding.animeSourceNameContainer.isGone = offline
|
||||
binding.animeSourceSettings.isGone = offline
|
||||
binding.animeSourceSearch.isGone = offline
|
||||
binding.animeSourceTitle.isGone = offline
|
||||
binding.mediaSourceNameContainer.isGone = offline
|
||||
binding.mediaSourceSettings.isGone = offline
|
||||
binding.mediaSourceSearch.isGone = offline
|
||||
binding.mediaSourceTitle.isGone = offline
|
||||
|
||||
//Source Selection
|
||||
// Source Selection
|
||||
var source =
|
||||
media.selected!!.sourceIndex.let { if (it >= watchSources.names.size) 0 else it }
|
||||
setLanguageList(media.selected!!.langIndex, source)
|
||||
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
|
||||
binding.animeSource.setText(watchSources.names[source])
|
||||
binding.mediaSource.setText(watchSources.names[source])
|
||||
watchSources[source].apply {
|
||||
this.selectDub = media.selected!!.preferDub
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
binding.animeSourceDubbedCont.isVisible = isDubAvailableSeparately()
|
||||
}
|
||||
}
|
||||
|
||||
binding.animeSource.setAdapter(
|
||||
binding.mediaSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
watchSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSourceTitle.isSelected = true
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSourceTitle.isSelected = true
|
||||
binding.mediaSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
changing = true
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
changing = false
|
||||
|
@ -150,15 +148,15 @@ class AnimeWatchAdapter(
|
|||
fragment.loadEpisodes(i, false)
|
||||
}
|
||||
|
||||
binding.animeSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
// Check if 'extension' and 'selected' properties exist and are accessible
|
||||
(watchSources[source] as? DynamicAnimeParser)?.let { ext ->
|
||||
ext.sourceLanguage = i
|
||||
fragment.onLangChange(i)
|
||||
fragment.onSourceChange(media.selected!!.sourceIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
{ MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
changing = true
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
changing = false
|
||||
|
@ -170,19 +168,19 @@ class AnimeWatchAdapter(
|
|||
} ?: run { }
|
||||
}
|
||||
|
||||
//settings
|
||||
binding.animeSourceSettings.setOnClickListener {
|
||||
// Settings
|
||||
binding.mediaSourceSettings.setOnClickListener {
|
||||
(watchSources[source] as? DynamicAnimeParser)?.let { ext ->
|
||||
fragment.openSettings(ext.extension)
|
||||
}
|
||||
}
|
||||
|
||||
//Icons
|
||||
// Icons
|
||||
|
||||
//subscribe
|
||||
// Subscribe
|
||||
subscribe = MediaDetailsActivity.PopImageButton(
|
||||
fragment.lifecycleScope,
|
||||
binding.animeSourceSubscribe,
|
||||
binding.mediaSourceSubscribe,
|
||||
R.drawable.ic_round_notifications_active_24,
|
||||
R.drawable.ic_round_notifications_none_24,
|
||||
R.color.bg_opp,
|
||||
|
@ -190,117 +188,115 @@ class AnimeWatchAdapter(
|
|||
fragment.subscribed,
|
||||
true
|
||||
) {
|
||||
fragment.onNotificationPressed(it, binding.animeSource.text.toString())
|
||||
fragment.onNotificationPressed(it, binding.mediaSource.text.toString())
|
||||
}
|
||||
|
||||
subscribeButton(false)
|
||||
|
||||
binding.animeSourceSubscribe.setOnLongClickListener {
|
||||
binding.mediaSourceSubscribe.setOnLongClickListener {
|
||||
openSettings(fragment.requireContext(), CHANNEL_SUBSCRIPTION_CHECK)
|
||||
}
|
||||
|
||||
//Nested Button
|
||||
binding.animeNestedButton.setOnClickListener {
|
||||
val dialogView =
|
||||
LayoutInflater.from(fragment.requireContext()).inflate(R.layout.dialog_layout, null)
|
||||
val dialogBinding = DialogLayoutBinding.bind(dialogView)
|
||||
var refresh = false
|
||||
var run = false
|
||||
var reversed = media.selected!!.recyclerReversed
|
||||
var style =
|
||||
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.AnimeDefaultView)
|
||||
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
|
||||
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
dialogBinding.animeSourceTop.setOnClickListener {
|
||||
reversed = !reversed
|
||||
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
|
||||
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
run = true
|
||||
}
|
||||
//Grids
|
||||
var selected = when (style) {
|
||||
0 -> dialogBinding.animeSourceList
|
||||
1 -> dialogBinding.animeSourceGrid
|
||||
2 -> dialogBinding.animeSourceCompact
|
||||
else -> dialogBinding.animeSourceList
|
||||
}
|
||||
when (style) {
|
||||
0 -> dialogBinding.layoutText.setText(R.string.list)
|
||||
1 -> dialogBinding.layoutText.setText(R.string.grid)
|
||||
2 -> dialogBinding.layoutText.setText(R.string.compact)
|
||||
else -> dialogBinding.animeSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
fun selected(it: ImageButton) {
|
||||
selected.alpha = 0.33f
|
||||
selected = it
|
||||
selected.alpha = 1f
|
||||
}
|
||||
dialogBinding.animeSourceList.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 0
|
||||
dialogBinding.layoutText.setText(R.string.list)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeSourceGrid.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 1
|
||||
dialogBinding.layoutText.setText(R.string.grid)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeSourceCompact.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 2
|
||||
dialogBinding.layoutText.setText(R.string.compact)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeWebviewContainer.setOnClickListener {
|
||||
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
|
||||
toast(R.string.webview_not_installed)
|
||||
// Nested Button
|
||||
binding.mediaNestedButton.setOnClickListener {
|
||||
val dialogBinding = DialogLayoutBinding.inflate(fragment.layoutInflater)
|
||||
dialogBinding.apply {
|
||||
var refresh = false
|
||||
var run = false
|
||||
var reversed = media.selected!!.recyclerReversed
|
||||
var style =
|
||||
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.AnimeDefaultView)
|
||||
|
||||
mediaSourceTop.rotation = if (reversed) -90f else 90f
|
||||
sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
mediaSourceTop.setOnClickListener {
|
||||
reversed = !reversed
|
||||
mediaSourceTop.rotation = if (reversed) -90f else 90f
|
||||
sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
run = true
|
||||
}
|
||||
//start CookieCatcher activity
|
||||
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
|
||||
val sourceAHH = watchSources[source] as? DynamicAnimeParser
|
||||
val sourceHttp =
|
||||
sourceAHH?.extension?.sources?.firstOrNull() as? AnimeHttpSource
|
||||
val url = sourceHttp?.baseUrl
|
||||
url?.let {
|
||||
refresh = true
|
||||
val headersMap = try {
|
||||
sourceHttp.headers.toMultimap()
|
||||
.mapValues { it.value.getOrNull(0) ?: "" }
|
||||
} catch (e: Exception) {
|
||||
emptyMap()
|
||||
// Grids
|
||||
var selected = when (style) {
|
||||
0 -> mediaSourceList
|
||||
1 -> mediaSourceGrid
|
||||
2 -> mediaSourceCompact
|
||||
else -> mediaSourceList
|
||||
}
|
||||
when (style) {
|
||||
0 -> layoutText.setText(R.string.list)
|
||||
1 -> layoutText.setText(R.string.grid)
|
||||
2 -> layoutText.setText(R.string.compact)
|
||||
else -> mediaSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
fun selected(it: ImageButton) {
|
||||
selected.alpha = 0.33f
|
||||
selected = it
|
||||
selected.alpha = 1f
|
||||
}
|
||||
mediaSourceList.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 0
|
||||
layoutText.setText(R.string.list)
|
||||
run = true
|
||||
}
|
||||
mediaSourceGrid.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 1
|
||||
layoutText.setText(R.string.grid)
|
||||
run = true
|
||||
}
|
||||
mediaSourceCompact.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 2
|
||||
layoutText.setText(R.string.compact)
|
||||
run = true
|
||||
}
|
||||
mediaWebviewContainer.setOnClickListener {
|
||||
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
|
||||
toast(R.string.webview_not_installed)
|
||||
}
|
||||
// Start CookieCatcher activity
|
||||
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
|
||||
val sourceAHH = watchSources[source] as? DynamicAnimeParser
|
||||
val sourceHttp =
|
||||
sourceAHH?.extension?.sources?.firstOrNull() as? AnimeHttpSource
|
||||
val url = sourceHttp?.baseUrl
|
||||
url?.let {
|
||||
refresh = true
|
||||
val headersMap = try {
|
||||
sourceHttp.headers.toMultimap()
|
||||
.mapValues { it.value.getOrNull(0) ?: "" }
|
||||
} catch (e: Exception) {
|
||||
emptyMap()
|
||||
}
|
||||
val intent =
|
||||
Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
.putExtra("headers", headersMap as HashMap<String, String>)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
val intent = Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
.putExtra("headers", headersMap as HashMap<String, String>)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
}
|
||||
|
||||
// Hidden
|
||||
mangaScanlatorContainer.visibility = View.GONE
|
||||
animeDownloadContainer.visibility = View.GONE
|
||||
fragment.requireContext().customAlertDialog().apply {
|
||||
setTitle("Options")
|
||||
setCustomView(dialogBinding.root)
|
||||
setPosButton("OK") {
|
||||
if (run) fragment.onIconPressed(style, reversed)
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
setNegButton("Cancel") {
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
//hidden
|
||||
dialogBinding.animeScanlatorContainer.visibility = View.GONE
|
||||
dialogBinding.animeDownloadContainer.visibility = View.GONE
|
||||
|
||||
nestedDialog = AlertDialog.Builder(fragment.requireContext(), R.style.MyPopup)
|
||||
.setTitle("Options")
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
if (run) fragment.onIconPressed(style, reversed)
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
.setNegativeButton("Cancel") { _, _ ->
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
.setOnCancelListener {
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
.create()
|
||||
nestedDialog?.show()
|
||||
}
|
||||
//Episode Handling
|
||||
// Episode Handling
|
||||
handleEpisodes()
|
||||
}
|
||||
|
||||
|
@ -308,7 +304,7 @@ class AnimeWatchAdapter(
|
|||
subscribe?.enabled(enabled)
|
||||
}
|
||||
|
||||
//Chips
|
||||
// Chips
|
||||
fun updateChips(limit: Int, names: Array<String>, arr: Array<Int>, selected: Int = 0) {
|
||||
val binding = _binding
|
||||
if (binding != null) {
|
||||
|
@ -319,13 +315,13 @@ class AnimeWatchAdapter(
|
|||
val chip =
|
||||
ItemChipBinding.inflate(
|
||||
LayoutInflater.from(fragment.context),
|
||||
binding.animeSourceChipGroup,
|
||||
binding.mediaSourceChipGroup,
|
||||
false
|
||||
).root
|
||||
chip.isCheckable = true
|
||||
fun selected() {
|
||||
chip.isChecked = true
|
||||
binding.animeWatchChipScroll.smoothScrollTo(
|
||||
binding.mediaWatchChipScroll.smoothScrollTo(
|
||||
(chip.left - screenWidth / 2) + (chip.width / 2),
|
||||
0
|
||||
)
|
||||
|
@ -344,14 +340,14 @@ class AnimeWatchAdapter(
|
|||
selected()
|
||||
fragment.onChipClicked(position, limit * (position), last - 1)
|
||||
}
|
||||
binding.animeSourceChipGroup.addView(chip)
|
||||
binding.mediaSourceChipGroup.addView(chip)
|
||||
if (selected == position) {
|
||||
selected()
|
||||
select = chip
|
||||
}
|
||||
}
|
||||
if (select != null)
|
||||
binding.animeWatchChipScroll.apply {
|
||||
binding.mediaWatchChipScroll.apply {
|
||||
post {
|
||||
scrollTo(
|
||||
(select.left - screenWidth / 2) + (select.width / 2),
|
||||
|
@ -363,7 +359,7 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
|
||||
fun clearChips() {
|
||||
_binding?.animeSourceChipGroup?.removeAllViews()
|
||||
_binding?.mediaSourceChipGroup?.removeAllViews()
|
||||
}
|
||||
|
||||
fun handleEpisodes() {
|
||||
|
@ -379,15 +375,15 @@ class AnimeWatchAdapter(
|
|||
|
||||
var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString()
|
||||
if (episodes.contains(continueEp)) {
|
||||
binding.animeSourceContinue.visibility = View.VISIBLE
|
||||
binding.sourceContinue.visibility = View.VISIBLE
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
continueEp
|
||||
)
|
||||
if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight > PrefManager.getVal<Float>(
|
||||
if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight > PrefManager.getVal<Float>(
|
||||
PrefName.WatchPercentage
|
||||
)
|
||||
) {
|
||||
|
@ -395,9 +391,9 @@ class AnimeWatchAdapter(
|
|||
if (e != -1 && e + 1 < episodes.size) {
|
||||
continueEp = episodes[e + 1]
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
continueEp
|
||||
)
|
||||
|
@ -407,51 +403,63 @@ class AnimeWatchAdapter(
|
|||
|
||||
val cleanedTitle = ep.title?.let { MediaNameAdapter.removeEpisodeNumber(it) }
|
||||
|
||||
binding.itemEpisodeImage.loadImage(
|
||||
binding.itemMediaImage.loadImage(
|
||||
ep.thumb ?: FileUrl[media.banner ?: media.cover], 0
|
||||
)
|
||||
if (ep.filler) binding.itemEpisodeFillerView.visibility = View.VISIBLE
|
||||
|
||||
binding.animeSourceContinueText.text =
|
||||
binding.mediaSourceContinueText.text =
|
||||
currActivity()!!.getString(
|
||||
R.string.continue_episode, ep.number, if (ep.filler)
|
||||
currActivity()!!.getString(R.string.filler_tag)
|
||||
else
|
||||
"", cleanedTitle
|
||||
)
|
||||
binding.animeSourceContinue.setOnClickListener {
|
||||
binding.sourceContinue.setOnClickListener {
|
||||
fragment.onEpisodeClick(continueEp)
|
||||
}
|
||||
if (fragment.continueEp) {
|
||||
if (
|
||||
(binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams)
|
||||
(binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams)
|
||||
.weight < PrefManager.getVal<Float>(PrefName.WatchPercentage)
|
||||
) {
|
||||
binding.animeSourceContinue.performClick()
|
||||
binding.sourceContinue.performClick()
|
||||
fragment.continueEp = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.animeSourceContinue.visibility = View.GONE
|
||||
binding.sourceContinue.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.animeSourceProgressBar.visibility = View.GONE
|
||||
binding.sourceProgressBar.visibility = View.GONE
|
||||
|
||||
val sourceFound = media.anime.episodes!!.isNotEmpty()
|
||||
binding.animeSourceNotFound.isGone = sourceFound
|
||||
val isDownloadedSource = watchSources[media.selected!!.sourceIndex] is OfflineAnimeParser
|
||||
|
||||
if (isDownloadedSource) {
|
||||
binding.sourceNotFound.text = if (sourceFound) {
|
||||
currActivity()!!.getString(R.string.source_not_found)
|
||||
} else {
|
||||
currActivity()!!.getString(R.string.download_not_found)
|
||||
}
|
||||
} else {
|
||||
binding.sourceNotFound.text = currActivity()!!.getString(R.string.source_not_found)
|
||||
}
|
||||
|
||||
binding.sourceNotFound.isGone = sourceFound
|
||||
binding.faqbutton.isGone = sourceFound
|
||||
|
||||
if (!sourceFound && PrefManager.getVal(PrefName.SearchSources) && autoSelect) {
|
||||
if (binding.animeSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
if (binding.mediaSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
val nextIndex = media.selected!!.sourceIndex + 1
|
||||
binding.animeSource.setText(
|
||||
binding.animeSource.adapter
|
||||
binding.mediaSource.setText(
|
||||
binding.mediaSource.adapter
|
||||
.getItem(nextIndex).toString(), false
|
||||
)
|
||||
fragment.onSourceChange(nextIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
{ MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
binding.animeSourceDubbedCont.isVisible = isDubAvailableSeparately()
|
||||
setLanguageList(0, nextIndex)
|
||||
|
@ -460,13 +468,13 @@ class AnimeWatchAdapter(
|
|||
fragment.loadEpisodes(nextIndex, false)
|
||||
}
|
||||
}
|
||||
binding.animeSource.setOnClickListener { autoSelect = false }
|
||||
binding.mediaSource.setOnClickListener { autoSelect = false }
|
||||
} else {
|
||||
binding.animeSourceContinue.visibility = View.GONE
|
||||
binding.animeSourceNotFound.visibility = View.GONE
|
||||
binding.sourceContinue.visibility = View.GONE
|
||||
binding.sourceNotFound.visibility = View.GONE
|
||||
binding.faqbutton.visibility = View.GONE
|
||||
clearChips()
|
||||
binding.animeSourceProgressBar.visibility = View.VISIBLE
|
||||
binding.sourceProgressBar.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -480,9 +488,9 @@ class AnimeWatchAdapter(
|
|||
ext.sourceLanguage = lang
|
||||
}
|
||||
try {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
binding?.mediaSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(
|
||||
binding?.mediaSourceLanguage?.setText(
|
||||
parser.extension.sources.firstOrNull()?.lang ?: "Unknown"
|
||||
)
|
||||
}
|
||||
|
@ -493,9 +501,9 @@ class AnimeWatchAdapter(
|
|||
)
|
||||
val items = adapter.count
|
||||
|
||||
binding?.animeSourceLanguageContainer?.visibility =
|
||||
binding?.mediaSourceLanguageContainer?.visibility =
|
||||
if (items > 1) View.VISIBLE else View.GONE
|
||||
binding?.animeSourceLanguage?.setAdapter(adapter)
|
||||
binding?.mediaSourceLanguage?.setAdapter(adapter)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -503,7 +511,7 @@ class AnimeWatchAdapter(
|
|||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) :
|
||||
inner class ViewHolder(val binding: ItemMediaSourceBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
displayTimer(media, binding.animeSourceContainer)
|
||||
|
|
|
@ -32,7 +32,7 @@ import ani.dantotsu.FileUrl
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.addons.download.DownloadAddonManager
|
||||
import ani.dantotsu.connections.anilist.api.MediaStreamingEpisode
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.FragmentMediaSourceBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.compareName
|
||||
|
@ -63,6 +63,7 @@ import ani.dantotsu.toast
|
|||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.accessAlertDialog
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.hasDirAccess
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.anggrayudi.storage.file.extension
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
|
@ -80,7 +81,7 @@ import kotlin.math.max
|
|||
import kotlin.math.roundToInt
|
||||
|
||||
class AnimeWatchFragment : Fragment() {
|
||||
private var _binding: FragmentAnimeWatchBinding? = null
|
||||
private var _binding: FragmentMediaSourceBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val model: MediaDetailsViewModel by activityViewModels()
|
||||
|
||||
|
@ -107,7 +108,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentAnimeWatchBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentMediaSourceBinding.inflate(inflater, container, false)
|
||||
return _binding?.root
|
||||
}
|
||||
|
||||
|
@ -128,7 +129,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
)
|
||||
|
||||
|
||||
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
|
||||
binding.mediaSourceRecycler.updatePadding(bottom = binding.mediaSourceRecycler.paddingBottom + navBarHeight)
|
||||
screenWidth = resources.displayMetrics.widthPixels.dp
|
||||
|
||||
var maxGridSize = (screenWidth / 100f).roundToInt()
|
||||
|
@ -152,13 +153,13 @@ class AnimeWatchFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
binding.animeSourceRecycler.layoutManager = gridLayoutManager
|
||||
binding.mediaSourceRecycler.layoutManager = gridLayoutManager
|
||||
|
||||
binding.ScrollTop.setOnClickListener {
|
||||
binding.animeSourceRecycler.scrollToPosition(10)
|
||||
binding.animeSourceRecycler.smoothScrollToPosition(0)
|
||||
binding.mediaSourceRecycler.scrollToPosition(10)
|
||||
binding.mediaSourceRecycler.smoothScrollToPosition(0)
|
||||
}
|
||||
binding.animeSourceRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
binding.mediaSourceRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
|
||||
|
@ -172,7 +173,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
}
|
||||
})
|
||||
model.scrolledToTop.observe(viewLifecycleOwner) {
|
||||
if (it) binding.animeSourceRecycler.scrollToPosition(0)
|
||||
if (it) binding.mediaSourceRecycler.scrollToPosition(0)
|
||||
}
|
||||
|
||||
continueEp = model.continueMedia ?: false
|
||||
|
@ -205,7 +206,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
offlineMode = offlineMode
|
||||
)
|
||||
|
||||
binding.animeSourceRecycler.adapter =
|
||||
binding.mediaSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, episodeAdapter)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
@ -266,7 +267,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
}
|
||||
media.anime?.episodes = episodes
|
||||
|
||||
//CHIP GROUP
|
||||
// CHIP GROUP
|
||||
val total = episodes.size
|
||||
val divisions = total.toDouble() / 10
|
||||
start = 0
|
||||
|
@ -396,20 +397,18 @@ class AnimeWatchFragment : Fragment() {
|
|||
if (allSettings.size > 1) {
|
||||
val names =
|
||||
allSettings.map { LanguageMapper.getLanguageName(it.lang) }.toTypedArray()
|
||||
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, -1) { dialog, which ->
|
||||
requireContext()
|
||||
.customAlertDialog()
|
||||
.apply {
|
||||
setTitle("Select a Source")
|
||||
singleChoiceItems(names) { which ->
|
||||
selectedSetting = allSettings[which]
|
||||
itemSelected = true
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
requireActivity().runOnUiThread {
|
||||
val fragment =
|
||||
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
|
@ -417,13 +416,13 @@ class AnimeWatchFragment : Fragment() {
|
|||
.commit()
|
||||
}
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismiss {
|
||||
if (!itemSelected) {
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
requireActivity().runOnUiThread {
|
||||
|
@ -432,11 +431,12 @@ class AnimeWatchFragment : Fragment() {
|
|||
changeUIVisibility(true)
|
||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
parentFragmentManager.beginTransaction().apply {
|
||||
setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
addToBackStack(null)
|
||||
commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -635,7 +635,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
private fun reload() {
|
||||
val selected = model.loadSelected(media)
|
||||
|
||||
//Find latest episode for subscription
|
||||
// Find latest episode for subscription
|
||||
selected.latest =
|
||||
media.anime?.episodes?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest =
|
||||
|
@ -679,14 +679,14 @@ class AnimeWatchFragment : Fragment() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.mediaInfoProgressBar.visibility = progress
|
||||
binding.animeSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
binding.mediaSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
|
||||
requireActivity().setNavigationTheme()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
state = binding.animeSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
state = binding.mediaSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -23,6 +23,7 @@ import ani.dantotsu.media.MediaNameAdapter
|
|||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -106,8 +107,8 @@ class EpisodeAdapter(
|
|||
|
||||
val thumb =
|
||||
ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null }
|
||||
Glide.with(binding.itemEpisodeImage).load(thumb ?: media.cover).override(400, 0)
|
||||
.into(binding.itemEpisodeImage)
|
||||
Glide.with(binding.itemMediaImage).load(thumb ?: media.cover).override(400, 0)
|
||||
.into(binding.itemMediaImage)
|
||||
binding.itemEpisodeNumber.text = ep.number
|
||||
binding.itemEpisodeTitle.text = if (ep.number == title) "Episode $title" else title
|
||||
|
||||
|
@ -140,9 +141,9 @@ class EpisodeAdapter(
|
|||
}
|
||||
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
ep.number
|
||||
)
|
||||
|
@ -154,8 +155,8 @@ class EpisodeAdapter(
|
|||
|
||||
val thumb =
|
||||
ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null }
|
||||
Glide.with(binding.itemEpisodeImage).load(thumb ?: media.cover).override(400, 0)
|
||||
.into(binding.itemEpisodeImage)
|
||||
Glide.with(binding.itemMediaImage).load(thumb ?: media.cover).override(400, 0)
|
||||
.into(binding.itemMediaImage)
|
||||
|
||||
binding.itemEpisodeNumber.text = ep.number
|
||||
binding.itemEpisodeTitle.text = title
|
||||
|
@ -183,9 +184,9 @@ class EpisodeAdapter(
|
|||
binding.itemEpisodeViewed.visibility = View.GONE
|
||||
}
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
ep.number
|
||||
)
|
||||
|
@ -208,9 +209,9 @@ class EpisodeAdapter(
|
|||
}
|
||||
}
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
ep.number
|
||||
)
|
||||
|
@ -318,16 +319,14 @@ class EpisodeAdapter(
|
|||
fragment.onAnimeEpisodeStopDownloadClick(episodeNumber)
|
||||
return@setOnClickListener
|
||||
} else if (downloadedEpisodes.contains(episodeNumber)) {
|
||||
val builder = AlertDialog.Builder(currContext(), R.style.MyPopup)
|
||||
builder.setTitle("Delete Episode")
|
||||
builder.setMessage("Are you sure you want to delete Episode ${episodeNumber}?")
|
||||
builder.setPositiveButton("Yes") { _, _ ->
|
||||
fragment.onAnimeEpisodeRemoveDownloadClick(episodeNumber)
|
||||
}
|
||||
builder.setNegativeButton("No") { _, _ ->
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
binding.root.context.customAlertDialog().apply {
|
||||
setTitle("Delete Episode")
|
||||
setMessage("Are you sure you want to delete Episode $episodeNumber?")
|
||||
setPosButton(R.string.yes) {
|
||||
fragment.onAnimeEpisodeRemoveDownloadClick(episodeNumber)
|
||||
}
|
||||
setNegButton(R.string.no)
|
||||
}.show()
|
||||
return@setOnClickListener
|
||||
} else {
|
||||
fragment.onAnimeEpisodeDownloadClick(episodeNumber)
|
||||
|
|
|
@ -444,15 +444,12 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
if (subtitles.isNotEmpty()) {
|
||||
val subtitleNames = subtitles.map { it.language }
|
||||
var subtitleToDownload: Subtitle? = null
|
||||
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.download_subtitle)
|
||||
.setSingleChoiceItems(
|
||||
subtitleNames.toTypedArray(),
|
||||
-1
|
||||
) { _, which ->
|
||||
requireActivity().customAlertDialog().apply {
|
||||
setTitle(R.string.download_subtitle)
|
||||
singleChoiceItems(subtitleNames.toTypedArray()) {which ->
|
||||
subtitleToDownload = subtitles[which]
|
||||
}
|
||||
.setPositiveButton(R.string.download) { dialog, _ ->
|
||||
setPosButton(R.string.download) {
|
||||
scope.launch {
|
||||
if (subtitleToDownload != null) {
|
||||
SubtitleDownloader.downloadSubtitle(
|
||||
|
@ -466,13 +463,9 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
)
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
setNegButton(R.string.cancel) {}
|
||||
}.show()
|
||||
} else {
|
||||
snackString(R.string.no_subtitles_available)
|
||||
}
|
||||
|
@ -576,65 +569,63 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
if (audioTracks.isNotEmpty()) {
|
||||
val audioNamesArray = audioTracks.toTypedArray()
|
||||
val checkedItems = BooleanArray(audioNamesArray.size) { false }
|
||||
val alertDialog = AlertDialog.Builder(currContext, R.style.MyPopup)
|
||||
.setTitle(R.string.download_audio_tracks)
|
||||
.setMultiChoiceItems(audioNamesArray, checkedItems) { _, which, isChecked ->
|
||||
val audioPair = Pair(extractor.audioTracks[which].url, extractor.audioTracks[which].lang)
|
||||
if (isChecked) {
|
||||
selectedAudioTracks.add(audioPair)
|
||||
} else {
|
||||
selectedAudioTracks.remove(audioPair)
|
||||
|
||||
currContext.customAlertDialog().apply{ // ToTest
|
||||
setTitle(R.string.download_audio_tracks)
|
||||
multiChoiceItems(audioNamesArray, checkedItems) {
|
||||
it.forEachIndexed { index, isChecked ->
|
||||
val audioPair = Pair(extractor.audioTracks[index].url, extractor.audioTracks[index].lang)
|
||||
if (isChecked) {
|
||||
selectedAudioTracks.add(audioPair)
|
||||
} else {
|
||||
selectedAudioTracks.remove(audioPair)
|
||||
}
|
||||
}
|
||||
}
|
||||
.setPositiveButton(R.string.download) { _, _ ->
|
||||
dialog?.dismiss()
|
||||
setPosButton(R.string.download) {
|
||||
go()
|
||||
}
|
||||
.setNegativeButton(R.string.skip) { dialog, _ ->
|
||||
setNegButton(R.string.skip) {
|
||||
selectedAudioTracks = mutableListOf()
|
||||
go()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.cancel) { dialog, _ ->
|
||||
setNeutralButton(R.string.cancel) {
|
||||
selectedAudioTracks = mutableListOf()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
go()
|
||||
}
|
||||
}
|
||||
if (subtitles.isNotEmpty()) {
|
||||
if (subtitles.isNotEmpty()) { // ToTest
|
||||
val subtitleNamesArray = subtitleNames.toTypedArray()
|
||||
val checkedItems = BooleanArray(subtitleNamesArray.size) { false }
|
||||
|
||||
val alertDialog = AlertDialog.Builder(currContext, R.style.MyPopup)
|
||||
.setTitle(R.string.download_subtitle)
|
||||
.setMultiChoiceItems(subtitleNamesArray, checkedItems) { _, which, isChecked ->
|
||||
val subtitlePair = Pair(subtitles[which].file.url, subtitles[which].language)
|
||||
if (isChecked) {
|
||||
selectedSubtitles.add(subtitlePair)
|
||||
} else {
|
||||
selectedSubtitles.remove(subtitlePair)
|
||||
currContext.customAlertDialog().apply {
|
||||
setTitle(R.string.download_subtitle)
|
||||
multiChoiceItems(subtitleNamesArray, checkedItems) {
|
||||
it.forEachIndexed { index, isChecked ->
|
||||
val subtitlePair = Pair(subtitles[index].file.url, subtitles[index].language)
|
||||
if (isChecked) {
|
||||
selectedSubtitles.add(subtitlePair)
|
||||
} else {
|
||||
selectedSubtitles.remove(subtitlePair)
|
||||
}
|
||||
}
|
||||
}
|
||||
.setPositiveButton(R.string.download) { _, _ ->
|
||||
dialog?.dismiss()
|
||||
setPosButton(R.string.download) {
|
||||
checkAudioTracks()
|
||||
}
|
||||
.setNegativeButton(R.string.skip) { dialog, _ ->
|
||||
setNegButton(R.string.skip) {
|
||||
selectedSubtitles = mutableListOf()
|
||||
checkAudioTracks()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.cancel) { dialog, _ ->
|
||||
setNeutralButton(R.string.cancel) {
|
||||
selectedSubtitles = mutableListOf()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
checkAudioTracks()
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import ani.dantotsu.setAnimation
|
|||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.ColorEditor.Companion.adjustColorForContrast
|
||||
import ani.dantotsu.util.ColorEditor.Companion.getContrastRatio
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.Section
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
|
@ -385,19 +386,14 @@ class CommentItem(
|
|||
* @param callback the callback to call when the user clicks yes
|
||||
*/
|
||||
private fun dialogBuilder(title: String, message: String, callback: () -> Unit) {
|
||||
val alertDialog =
|
||||
android.app.AlertDialog.Builder(commentsFragment.activity, R.style.MyPopup)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton("Yes") { dialog, _ ->
|
||||
callback()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
commentsFragment.activity.customAlertDialog().apply {
|
||||
setTitle(title)
|
||||
setMessage(message)
|
||||
setPosButton("Yes") {
|
||||
callback()
|
||||
}
|
||||
setNegButton("No") {}
|
||||
}.show()
|
||||
}
|
||||
|
||||
private val usernameColors: Array<String> = arrayOf(
|
||||
|
|
|
@ -25,6 +25,7 @@ import ani.dantotsu.connections.anilist.Anilist
|
|||
import ani.dantotsu.connections.comments.Comment
|
||||
import ani.dantotsu.connections.comments.CommentResponse
|
||||
import ani.dantotsu.connections.comments.CommentsAPI
|
||||
import ani.dantotsu.databinding.DialogEdittextBinding
|
||||
import ani.dantotsu.databinding.FragmentCommentsBinding
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
|
@ -34,6 +35,7 @@ import ani.dantotsu.settings.saving.PrefName
|
|||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.Section
|
||||
import io.noties.markwon.editor.MarkwonEditor
|
||||
|
@ -162,33 +164,26 @@ class CommentsFragment : Fragment() {
|
|||
}
|
||||
|
||||
binding.commentFilter.setOnClickListener {
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Enter a chapter/episode number tag")
|
||||
.setView(R.layout.dialog_edittext)
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
val editText =
|
||||
(dialog as AlertDialog).findViewById<EditText>(R.id.dialogEditText)
|
||||
val text = editText?.text.toString()
|
||||
activity.customAlertDialog().apply {
|
||||
val customView = DialogEdittextBinding.inflate(layoutInflater)
|
||||
setTitle("Enter a chapter/episode number tag")
|
||||
setCustomView(customView.root)
|
||||
setPosButton("OK") {
|
||||
val text = customView.dialogEditText.text.toString()
|
||||
filterTag = text.toIntOrNull()
|
||||
lifecycleScope.launch {
|
||||
loadAndDisplayComments()
|
||||
}
|
||||
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton("Clear") { dialog, _ ->
|
||||
setNeutralButton("Clear") {
|
||||
filterTag = null
|
||||
lifecycleScope.launch {
|
||||
loadAndDisplayComments()
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
filterTag = null
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
setNegButton("Cancel") { filterTag = null }
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
var isFetching = false
|
||||
|
@ -303,13 +298,12 @@ class CommentsFragment : Fragment() {
|
|||
|
||||
activity.binding.commentLabel.setOnClickListener {
|
||||
//alert dialog to enter a number, with a cancel and ok button
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Enter a chapter/episode number tag")
|
||||
.setView(R.layout.dialog_edittext)
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
val editText =
|
||||
(dialog as AlertDialog).findViewById<EditText>(R.id.dialogEditText)
|
||||
val text = editText?.text.toString()
|
||||
activity.customAlertDialog().apply {
|
||||
val customView = DialogEdittextBinding.inflate(layoutInflater)
|
||||
setTitle("Enter a chapter/episode number tag")
|
||||
setCustomView(customView.root)
|
||||
setPosButton("OK") {
|
||||
val text = customView.dialogEditText.text.toString()
|
||||
tag = text.toIntOrNull()
|
||||
if (tag == null) {
|
||||
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
|
||||
|
@ -324,28 +318,25 @@ class CommentsFragment : Fragment() {
|
|||
null
|
||||
)
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton("Clear") { dialog, _ ->
|
||||
setNeutralButton("Clear") {
|
||||
tag = null
|
||||
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
R.drawable.ic_label_off_24,
|
||||
null
|
||||
)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
setNegButton("Cancel") {
|
||||
tag = null
|
||||
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
R.drawable.ic_label_off_24,
|
||||
null
|
||||
)
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,12 +353,6 @@ class CommentsFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
@ -579,9 +564,9 @@ class CommentsFragment : Fragment() {
|
|||
* Called when the user tries to comment for the first time
|
||||
*/
|
||||
private fun showCommentRulesDialog() {
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Commenting Rules")
|
||||
.setMessage(
|
||||
activity.customAlertDialog().apply{
|
||||
setTitle("Commenting Rules")
|
||||
setMessage(
|
||||
"I WILL BAN YOU WITHOUT HESITATION\n" +
|
||||
"1. No racism\n" +
|
||||
"2. No hate speech\n" +
|
||||
|
@ -594,16 +579,13 @@ class CommentsFragment : Fragment() {
|
|||
"10. No illegal content\n" +
|
||||
"11. Anything you know you shouldn't comment\n"
|
||||
)
|
||||
.setPositiveButton("I Understand") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
setPosButton("I Understand") {
|
||||
PrefManager.setVal(PrefName.FirstComment, false)
|
||||
processComment()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun processComment() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ani.dantotsu.media.manga
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -19,8 +18,9 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.CustomDialogLayoutBinding
|
||||
import ani.dantotsu.databinding.DialogLayoutBinding
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemMediaSourceBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.loadImage
|
||||
|
@ -35,11 +35,13 @@ import ani.dantotsu.others.webview.CookieCatcher
|
|||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.parsers.MangaReadSources
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.parsers.OfflineMangaParser
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.FAQActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.chip.Chip
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
|
@ -55,31 +57,29 @@ class MangaReadAdapter(
|
|||
) : RecyclerView.Adapter<MangaReadAdapter.ViewHolder>() {
|
||||
|
||||
var subscribe: MediaDetailsActivity.PopImageButton? = null
|
||||
private var _binding: ItemAnimeWatchBinding? = null
|
||||
private var _binding: ItemMediaSourceBinding? = null
|
||||
val hiddenScanlators = mutableListOf<String>()
|
||||
var scanlatorSelectionListener: ScanlatorSelectionListener? = null
|
||||
var options = listOf<String>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val bind = ItemAnimeWatchBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val bind = ItemMediaSourceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(bind)
|
||||
}
|
||||
|
||||
private var nestedDialog: AlertDialog? = null
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
_binding = binding
|
||||
binding.sourceTitle.setText(R.string.chaps)
|
||||
|
||||
//Fuck u launch
|
||||
// Fuck u launch
|
||||
binding.faqbutton.setOnClickListener {
|
||||
val intent = Intent(fragment.requireContext(), FAQActivity::class.java)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
|
||||
//Wrong Title
|
||||
binding.animeSourceSearch.setOnClickListener {
|
||||
// Wrong Title
|
||||
binding.mediaSourceSearch.setOnClickListener {
|
||||
SourceSearchDialogFragment().show(
|
||||
fragment.requireActivity().supportFragmentManager,
|
||||
null
|
||||
|
@ -87,54 +87,54 @@ class MangaReadAdapter(
|
|||
}
|
||||
val offline = !isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||
|
||||
binding.animeSourceNameContainer.isGone = offline
|
||||
binding.animeSourceSettings.isGone = offline
|
||||
binding.animeSourceSearch.isGone = offline
|
||||
binding.animeSourceTitle.isGone = offline
|
||||
//Source Selection
|
||||
binding.mediaSourceNameContainer.isGone = offline
|
||||
binding.mediaSourceSettings.isGone = offline
|
||||
binding.mediaSourceSearch.isGone = offline
|
||||
binding.mediaSourceTitle.isGone = offline
|
||||
// Source Selection
|
||||
var source =
|
||||
media.selected!!.sourceIndex.let { if (it >= mangaReadSources.names.size) 0 else it }
|
||||
setLanguageList(media.selected!!.langIndex, source)
|
||||
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
|
||||
binding.animeSource.setText(mangaReadSources.names[source])
|
||||
binding.mediaSource.setText(mangaReadSources.names[source])
|
||||
mangaReadSources[source].apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
}
|
||||
}
|
||||
media.selected?.scanlators?.let {
|
||||
hiddenScanlators.addAll(it)
|
||||
}
|
||||
binding.animeSource.setAdapter(
|
||||
binding.mediaSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
mangaReadSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSourceTitle.isSelected = true
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSourceTitle.isSelected = true
|
||||
binding.mediaSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
source = i
|
||||
setLanguageList(0, i)
|
||||
}
|
||||
subscribeButton(false)
|
||||
//invalidate if it's the last source
|
||||
// Invalidate if it's the last source
|
||||
val invalidate = i == mangaReadSources.names.size - 1
|
||||
fragment.loadChapters(i, invalidate)
|
||||
}
|
||||
|
||||
binding.animeSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
// Check if 'extension' and 'selected' properties exist and are accessible
|
||||
(mangaReadSources[source] as? DynamicMangaParser)?.let { ext ->
|
||||
ext.sourceLanguage = i
|
||||
fragment.onLangChange(i, ext.saveName)
|
||||
fragment.onSourceChange(media.selected!!.sourceIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
{ MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
setLanguageList(i, source)
|
||||
}
|
||||
subscribeButton(false)
|
||||
|
@ -143,17 +143,17 @@ class MangaReadAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
//settings
|
||||
binding.animeSourceSettings.setOnClickListener {
|
||||
// Settings
|
||||
binding.mediaSourceSettings.setOnClickListener {
|
||||
(mangaReadSources[source] as? DynamicMangaParser)?.let { ext ->
|
||||
fragment.openSettings(ext.extension)
|
||||
}
|
||||
}
|
||||
|
||||
//Grids
|
||||
// Grids
|
||||
subscribe = MediaDetailsActivity.PopImageButton(
|
||||
fragment.lifecycleScope,
|
||||
binding.animeSourceSubscribe,
|
||||
binding.mediaSourceSubscribe,
|
||||
R.drawable.ic_round_notifications_active_24,
|
||||
R.drawable.ic_round_notifications_none_24,
|
||||
R.color.bg_opp,
|
||||
|
@ -161,206 +161,191 @@ class MangaReadAdapter(
|
|||
fragment.subscribed,
|
||||
true
|
||||
) {
|
||||
fragment.onNotificationPressed(it, binding.animeSource.text.toString())
|
||||
fragment.onNotificationPressed(it, binding.mediaSource.text.toString())
|
||||
}
|
||||
|
||||
subscribeButton(false)
|
||||
|
||||
binding.animeSourceSubscribe.setOnLongClickListener {
|
||||
binding.mediaSourceSubscribe.setOnLongClickListener {
|
||||
openSettings(fragment.requireContext(), CHANNEL_SUBSCRIPTION_CHECK)
|
||||
}
|
||||
|
||||
binding.animeNestedButton.setOnClickListener {
|
||||
|
||||
val dialogView =
|
||||
LayoutInflater.from(fragment.requireContext()).inflate(R.layout.dialog_layout, null)
|
||||
val dialogBinding = DialogLayoutBinding.bind(dialogView)
|
||||
binding.mediaNestedButton.setOnClickListener {
|
||||
val dialogBinding = DialogLayoutBinding.inflate(fragment.layoutInflater)
|
||||
var refresh = false
|
||||
var run = false
|
||||
var reversed = media.selected!!.recyclerReversed
|
||||
var style =
|
||||
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.MangaDefaultView)
|
||||
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
|
||||
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
dialogBinding.animeSourceTop.setOnClickListener {
|
||||
reversed = !reversed
|
||||
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
|
||||
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
run = true
|
||||
}
|
||||
dialogBinding.apply {
|
||||
mediaSourceTop.rotation = if (reversed) -90f else 90f
|
||||
sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
mediaSourceTop.setOnClickListener {
|
||||
reversed = !reversed
|
||||
mediaSourceTop.rotation = if (reversed) -90f else 90f
|
||||
sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
run = true
|
||||
}
|
||||
|
||||
//Grids
|
||||
dialogBinding.animeSourceGrid.visibility = View.GONE
|
||||
var selected = when (style) {
|
||||
0 -> dialogBinding.animeSourceList
|
||||
1 -> dialogBinding.animeSourceCompact
|
||||
else -> dialogBinding.animeSourceList
|
||||
}
|
||||
when (style) {
|
||||
0 -> dialogBinding.layoutText.setText(R.string.list)
|
||||
1 -> dialogBinding.layoutText.setText(R.string.compact)
|
||||
else -> dialogBinding.animeSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
fun selected(it: ImageButton) {
|
||||
selected.alpha = 0.33f
|
||||
selected = it
|
||||
// Grids
|
||||
mediaSourceGrid.visibility = View.GONE
|
||||
var selected = when (style) {
|
||||
0 -> mediaSourceList
|
||||
1 -> mediaSourceCompact
|
||||
else -> mediaSourceList
|
||||
}
|
||||
when (style) {
|
||||
0 -> layoutText.setText(R.string.list)
|
||||
1 -> layoutText.setText(R.string.compact)
|
||||
else -> mediaSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
}
|
||||
dialogBinding.animeSourceList.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 0
|
||||
dialogBinding.layoutText.setText(R.string.list)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeSourceCompact.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 1
|
||||
dialogBinding.layoutText.setText(R.string.compact)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeWebviewContainer.setOnClickListener {
|
||||
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
|
||||
toast(R.string.webview_not_installed)
|
||||
fun selected(it: ImageButton) {
|
||||
selected.alpha = 0.33f
|
||||
selected = it
|
||||
selected.alpha = 1f
|
||||
}
|
||||
//start CookieCatcher activity
|
||||
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
|
||||
val sourceAHH = mangaReadSources[source] as? DynamicMangaParser
|
||||
val sourceHttp = sourceAHH?.extension?.sources?.firstOrNull() as? HttpSource
|
||||
val url = sourceHttp?.baseUrl
|
||||
url?.let {
|
||||
refresh = true
|
||||
val intent = Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
mediaSourceList.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 0
|
||||
layoutText.setText(R.string.list)
|
||||
run = true
|
||||
}
|
||||
mediaSourceCompact.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 1
|
||||
layoutText.setText(R.string.compact)
|
||||
run = true
|
||||
}
|
||||
mediaWebviewContainer.setOnClickListener {
|
||||
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
|
||||
toast(R.string.webview_not_installed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Multi download
|
||||
dialogBinding.downloadNo.text = "0"
|
||||
dialogBinding.animeDownloadTop.setOnClickListener {
|
||||
//Alert dialog asking for the number of chapters to download
|
||||
val alertDialog = AlertDialog.Builder(currContext(), R.style.MyPopup)
|
||||
alertDialog.setTitle("Multi Chapter Downloader")
|
||||
alertDialog.setMessage("Enter the number of chapters to download")
|
||||
val input = NumberPicker(currContext())
|
||||
input.minValue = 1
|
||||
input.maxValue = 20
|
||||
input.value = 1
|
||||
alertDialog.setView(input)
|
||||
alertDialog.setPositiveButton("OK") { _, _ ->
|
||||
dialogBinding.downloadNo.text = "${input.value}"
|
||||
}
|
||||
alertDialog.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() }
|
||||
val dialog = alertDialog.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
|
||||
//Scanlator
|
||||
dialogBinding.animeScanlatorContainer.isVisible = options.count() > 1
|
||||
dialogBinding.scanlatorNo.text = "${options.count()}"
|
||||
dialogBinding.animeScanlatorTop.setOnClickListener {
|
||||
val dialogView2 =
|
||||
LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
|
||||
val checkboxContainer =
|
||||
dialogView2.findViewById<LinearLayout>(R.id.checkboxContainer)
|
||||
val tickAllButton = dialogView2.findViewById<ImageButton>(R.id.toggleButton)
|
||||
|
||||
// Function to get the right image resource for the toggle button
|
||||
fun getToggleImageResource(container: ViewGroup): Int {
|
||||
var allChecked = true
|
||||
var allUnchecked = true
|
||||
|
||||
for (i in 0 until container.childCount) {
|
||||
val checkBox = container.getChildAt(i) as CheckBox
|
||||
if (!checkBox.isChecked) {
|
||||
allChecked = false
|
||||
} else {
|
||||
allUnchecked = false
|
||||
// Start CookieCatcher activity
|
||||
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
|
||||
val sourceAHH = mangaReadSources[source] as? DynamicMangaParser
|
||||
val sourceHttp = sourceAHH?.extension?.sources?.firstOrNull() as? HttpSource
|
||||
val url = sourceHttp?.baseUrl
|
||||
url?.let {
|
||||
refresh = true
|
||||
val intent =
|
||||
Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
}
|
||||
return when {
|
||||
allChecked -> R.drawable.untick_all_boxes
|
||||
allUnchecked -> R.drawable.tick_all_boxes
|
||||
else -> R.drawable.invert_all_boxes
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamically add checkboxes
|
||||
options.forEach { option ->
|
||||
val checkBox = CheckBox(currContext()).apply {
|
||||
text = option
|
||||
setOnCheckedChangeListener { _, _ ->
|
||||
// Update image resource when you change a checkbox
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
// Multi download
|
||||
downloadNo.text = "0"
|
||||
mediaDownloadTop.setOnClickListener {
|
||||
// Alert dialog asking for the number of chapters to download
|
||||
fragment.requireContext().customAlertDialog().apply {
|
||||
setTitle("Multi Chapter Downloader")
|
||||
setMessage("Enter the number of chapters to download")
|
||||
val input = NumberPicker(currContext())
|
||||
input.minValue = 1
|
||||
input.maxValue = 20
|
||||
input.value = 1
|
||||
setCustomView(input)
|
||||
setPosButton(R.string.ok) {
|
||||
downloadNo.text = "${input.value}"
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
|
||||
// Set checked if its already selected
|
||||
if (media.selected!!.scanlators != null) {
|
||||
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
} else {
|
||||
checkBox.isChecked = true
|
||||
}
|
||||
checkboxContainer.addView(checkBox)
|
||||
}
|
||||
|
||||
// Create AlertDialog
|
||||
val dialog = AlertDialog.Builder(currContext(), R.style.MyPopup)
|
||||
.setView(dialogView2)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
hiddenScanlators.clear()
|
||||
for (i in 0 until checkboxContainer.childCount) {
|
||||
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
|
||||
// Scanlator
|
||||
mangaScanlatorContainer.isVisible = options.count() > 1
|
||||
scanlatorNo.text = "${options.count()}"
|
||||
mangaScanlatorTop.setOnClickListener {
|
||||
CustomDialogLayoutBinding.inflate(fragment.layoutInflater)
|
||||
val dialogView = CustomDialogLayoutBinding.inflate(fragment.layoutInflater)
|
||||
val checkboxContainer = dialogView.checkboxContainer
|
||||
val tickAllButton = dialogView.toggleButton
|
||||
|
||||
fun getToggleImageResource(container: ViewGroup): Int {
|
||||
var allChecked = true
|
||||
var allUnchecked = true
|
||||
|
||||
for (i in 0 until container.childCount) {
|
||||
val checkBox = container.getChildAt(i) as CheckBox
|
||||
if (!checkBox.isChecked) {
|
||||
hiddenScanlators.add(checkBox.text.toString())
|
||||
allChecked = false
|
||||
} else {
|
||||
allUnchecked = false
|
||||
}
|
||||
}
|
||||
fragment.onScanlatorChange(hiddenScanlators)
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
}
|
||||
.setNegativeButton("Cancel", null)
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
|
||||
// Standard image resource
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
|
||||
// Listens to ticked checkboxes and changes image resource accordingly
|
||||
tickAllButton.setOnClickListener {
|
||||
// Toggle checkboxes
|
||||
for (i in 0 until checkboxContainer.childCount) {
|
||||
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
|
||||
checkBox.isChecked = !checkBox.isChecked
|
||||
return when {
|
||||
allChecked -> R.drawable.untick_all_boxes
|
||||
allUnchecked -> R.drawable.tick_all_boxes
|
||||
else -> R.drawable.invert_all_boxes
|
||||
}
|
||||
}
|
||||
|
||||
// Update image resource
|
||||
options.forEach { option ->
|
||||
val checkBox = CheckBox(currContext()).apply {
|
||||
text = option
|
||||
setOnCheckedChangeListener { _, _ ->
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
}
|
||||
}
|
||||
|
||||
if (media.selected!!.scanlators != null) {
|
||||
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
} else {
|
||||
checkBox.isChecked = true
|
||||
}
|
||||
checkboxContainer.addView(checkBox)
|
||||
}
|
||||
|
||||
fragment.requireContext().customAlertDialog().apply {
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton("OK") {
|
||||
hiddenScanlators.clear()
|
||||
for (i in 0 until checkboxContainer.childCount) {
|
||||
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
|
||||
if (!checkBox.isChecked) {
|
||||
hiddenScanlators.add(checkBox.text.toString())
|
||||
}
|
||||
}
|
||||
fragment.onScanlatorChange(hiddenScanlators)
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
}
|
||||
setNegButton("Cancel")
|
||||
}.show()
|
||||
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
|
||||
tickAllButton.setOnClickListener {
|
||||
for (i in 0 until checkboxContainer.childCount) {
|
||||
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
|
||||
checkBox.isChecked = !checkBox.isChecked
|
||||
}
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
}
|
||||
}
|
||||
|
||||
fragment.requireContext().customAlertDialog().apply {
|
||||
setTitle("Options")
|
||||
setCustomView(root)
|
||||
setPosButton("OK") {
|
||||
if (run) fragment.onIconPressed(style, reversed)
|
||||
if (downloadNo.text != "0") {
|
||||
fragment.multiDownload(downloadNo.text.toString().toInt())
|
||||
}
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
setNegButton("Cancel") {
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
nestedDialog = AlertDialog.Builder(fragment.requireContext(), R.style.MyPopup)
|
||||
.setTitle("Options")
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
if (run) fragment.onIconPressed(style, reversed)
|
||||
if (dialogBinding.downloadNo.text != "0") {
|
||||
fragment.multiDownload(dialogBinding.downloadNo.text.toString().toInt())
|
||||
}
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
.setNegativeButton("Cancel") { _, _ ->
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
.setOnCancelListener {
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
.create()
|
||||
nestedDialog?.show()
|
||||
}
|
||||
//Chapter Handling
|
||||
// Chapter Handling
|
||||
handleChapters()
|
||||
}
|
||||
|
||||
|
@ -368,7 +353,7 @@ class MangaReadAdapter(
|
|||
subscribe?.enabled(enabled)
|
||||
}
|
||||
|
||||
//Chips
|
||||
// Chips
|
||||
fun updateChips(limit: Int, names: Array<String>, arr: Array<Int>, selected: Int = 0) {
|
||||
val binding = _binding
|
||||
if (binding != null) {
|
||||
|
@ -379,13 +364,13 @@ class MangaReadAdapter(
|
|||
val chip =
|
||||
ItemChipBinding.inflate(
|
||||
LayoutInflater.from(fragment.context),
|
||||
binding.animeSourceChipGroup,
|
||||
binding.mediaSourceChipGroup,
|
||||
false
|
||||
).root
|
||||
chip.isCheckable = true
|
||||
fun selected() {
|
||||
chip.isChecked = true
|
||||
binding.animeWatchChipScroll.smoothScrollTo(
|
||||
binding.mediaWatchChipScroll.smoothScrollTo(
|
||||
(chip.left - screenWidth / 2) + (chip.width / 2),
|
||||
0
|
||||
)
|
||||
|
@ -403,7 +388,7 @@ class MangaReadAdapter(
|
|||
} else {
|
||||
names[last - 1]
|
||||
}
|
||||
//chip.text = "${names[limit * (position)]} - ${names[last - 1]}"
|
||||
// chip.text = "${names[limit * (position)]} - ${names[last - 1]}"
|
||||
val chipText = "$startChapterString - $endChapterString"
|
||||
chip.text = chipText
|
||||
chip.setTextColor(
|
||||
|
@ -417,14 +402,14 @@ class MangaReadAdapter(
|
|||
selected()
|
||||
fragment.onChipClicked(position, limit * (position), last - 1)
|
||||
}
|
||||
binding.animeSourceChipGroup.addView(chip)
|
||||
binding.mediaSourceChipGroup.addView(chip)
|
||||
if (selected == position) {
|
||||
selected()
|
||||
select = chip
|
||||
}
|
||||
}
|
||||
if (select != null)
|
||||
binding.animeWatchChipScroll.apply {
|
||||
binding.mediaWatchChipScroll.apply {
|
||||
post {
|
||||
scrollTo(
|
||||
(select.left - screenWidth / 2) + (select.width / 2),
|
||||
|
@ -436,7 +421,7 @@ class MangaReadAdapter(
|
|||
}
|
||||
|
||||
fun clearChips() {
|
||||
_binding?.animeSourceChipGroup?.removeAllViews()
|
||||
_binding?.mediaSourceChipGroup?.removeAllViews()
|
||||
}
|
||||
|
||||
fun handleChapters() {
|
||||
|
@ -462,70 +447,86 @@ class MangaReadAdapter(
|
|||
}
|
||||
if (formattedChapters.contains(continueEp)) {
|
||||
continueEp = chapters[formattedChapters.indexOf(continueEp)]
|
||||
binding.animeSourceContinue.visibility = View.VISIBLE
|
||||
binding.sourceContinue.visibility = View.VISIBLE
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
continueEp
|
||||
)
|
||||
if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight > 0.8f) {
|
||||
if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight > 0.8f) {
|
||||
val e = chapters.indexOf(continueEp)
|
||||
if (e != -1 && e + 1 < chapters.size) {
|
||||
continueEp = chapters[e + 1]
|
||||
}
|
||||
}
|
||||
val ep = media.manga.chapters!![continueEp]!!
|
||||
binding.itemEpisodeImage.loadImage(media.banner ?: media.cover)
|
||||
binding.animeSourceContinueText.text =
|
||||
binding.itemMediaImage.loadImage(media.banner ?: media.cover)
|
||||
binding.mediaSourceContinueText.text =
|
||||
currActivity()!!.getString(
|
||||
R.string.continue_chapter,
|
||||
ep.number,
|
||||
if (!ep.title.isNullOrEmpty()) ep.title else ""
|
||||
)
|
||||
binding.animeSourceContinue.setOnClickListener {
|
||||
binding.sourceContinue.setOnClickListener {
|
||||
fragment.onMangaChapterClick(continueEp)
|
||||
}
|
||||
if (fragment.continueEp) {
|
||||
if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight < 0.8f) {
|
||||
binding.animeSourceContinue.performClick()
|
||||
if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight < 0.8f) {
|
||||
binding.sourceContinue.performClick()
|
||||
fragment.continueEp = false
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
binding.animeSourceContinue.visibility = View.GONE
|
||||
binding.sourceContinue.visibility = View.GONE
|
||||
}
|
||||
binding.animeSourceProgressBar.visibility = View.GONE
|
||||
val sourceFound = media.manga.chapters!!.isNotEmpty()
|
||||
binding.animeSourceNotFound.isGone = sourceFound
|
||||
|
||||
binding.sourceProgressBar.visibility = View.GONE
|
||||
|
||||
val sourceFound = filteredChapters.isNotEmpty()
|
||||
val isDownloadedSource = mangaReadSources[media.selected!!.sourceIndex] is OfflineMangaParser
|
||||
|
||||
if (isDownloadedSource) {
|
||||
binding.sourceNotFound.text = if (sourceFound) {
|
||||
currActivity()!!.getString(R.string.source_not_found)
|
||||
} else {
|
||||
currActivity()!!.getString(R.string.download_not_found)
|
||||
}
|
||||
} else {
|
||||
binding.sourceNotFound.text = currActivity()!!.getString(R.string.source_not_found)
|
||||
}
|
||||
|
||||
binding.sourceNotFound.isGone = sourceFound
|
||||
binding.faqbutton.isGone = sourceFound
|
||||
|
||||
|
||||
if (!sourceFound && PrefManager.getVal(PrefName.SearchSources)) {
|
||||
if (binding.animeSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
if (binding.mediaSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
val nextIndex = media.selected!!.sourceIndex + 1
|
||||
binding.animeSource.setText(
|
||||
binding.animeSource.adapter
|
||||
binding.mediaSource.setText(
|
||||
binding.mediaSource.adapter
|
||||
.getItem(nextIndex).toString(), false
|
||||
)
|
||||
fragment.onSourceChange(nextIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
{ MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
setLanguageList(0, nextIndex)
|
||||
}
|
||||
subscribeButton(false)
|
||||
// invalidate if it's the last source
|
||||
// Invalidate if it's the last source
|
||||
val invalidate = nextIndex == mangaReadSources.names.size - 1
|
||||
fragment.loadChapters(nextIndex, invalidate)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.animeSourceContinue.visibility = View.GONE
|
||||
binding.animeSourceNotFound.visibility = View.GONE
|
||||
binding.sourceContinue.visibility = View.GONE
|
||||
binding.sourceNotFound.visibility = View.GONE
|
||||
binding.faqbutton.visibility = View.GONE
|
||||
clearChips()
|
||||
binding.animeSourceProgressBar.visibility = View.VISIBLE
|
||||
binding.sourceProgressBar.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -539,9 +540,9 @@ class MangaReadAdapter(
|
|||
ext.sourceLanguage = lang
|
||||
}
|
||||
try {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
binding?.mediaSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(
|
||||
binding?.mediaSourceLanguage?.setText(
|
||||
parser.extension.sources.firstOrNull()?.lang ?: "Unknown"
|
||||
)
|
||||
}
|
||||
|
@ -551,9 +552,9 @@ class MangaReadAdapter(
|
|||
parser.extension.sources.map { LanguageMapper.getLanguageName(it.lang) }
|
||||
)
|
||||
val items = adapter.count
|
||||
binding?.animeSourceLanguageContainer?.isVisible = items > 1
|
||||
binding?.mediaSourceLanguageContainer?.isVisible = items > 1
|
||||
|
||||
binding?.animeSourceLanguage?.setAdapter(adapter)
|
||||
binding?.mediaSourceLanguage?.setAdapter(adapter)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -561,7 +562,7 @@ class MangaReadAdapter(
|
|||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) :
|
||||
inner class ViewHolder(val binding: ItemMediaSourceBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package ani.dantotsu.media.manga
|
|||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
@ -31,7 +30,7 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.FragmentMediaSourceBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.compareName
|
||||
|
@ -60,6 +59,7 @@ import ani.dantotsu.settings.saving.PrefName
|
|||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.accessAlertDialog
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.hasDirAccess
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
|
@ -74,7 +74,7 @@ import kotlin.math.max
|
|||
import kotlin.math.roundToInt
|
||||
|
||||
open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||
private var _binding: FragmentAnimeWatchBinding? = null
|
||||
private var _binding: FragmentMediaSourceBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val model: MediaDetailsViewModel by activityViewModels()
|
||||
|
||||
|
@ -101,7 +101,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentAnimeWatchBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentMediaSourceBinding.inflate(inflater, container, false)
|
||||
return _binding?.root
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
|
||||
binding.mediaSourceRecycler.updatePadding(bottom = binding.mediaSourceRecycler.paddingBottom + navBarHeight)
|
||||
screenWidth = resources.displayMetrics.widthPixels.dp
|
||||
|
||||
var maxGridSize = (screenWidth / 100f).roundToInt()
|
||||
|
@ -144,13 +144,13 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
}
|
||||
|
||||
binding.animeSourceRecycler.layoutManager = gridLayoutManager
|
||||
binding.mediaSourceRecycler.layoutManager = gridLayoutManager
|
||||
|
||||
binding.ScrollTop.setOnClickListener {
|
||||
binding.animeSourceRecycler.scrollToPosition(10)
|
||||
binding.animeSourceRecycler.smoothScrollToPosition(0)
|
||||
binding.mediaSourceRecycler.scrollToPosition(10)
|
||||
binding.mediaSourceRecycler.smoothScrollToPosition(0)
|
||||
}
|
||||
binding.animeSourceRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
binding.mediaSourceRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
|
||||
|
@ -164,7 +164,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
})
|
||||
model.scrolledToTop.observe(viewLifecycleOwner) {
|
||||
if (it) binding.animeSourceRecycler.scrollToPosition(0)
|
||||
if (it) binding.mediaSourceRecycler.scrollToPosition(0)
|
||||
}
|
||||
|
||||
continueEp = model.continueMedia ?: false
|
||||
|
@ -199,7 +199,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
}
|
||||
|
||||
binding.animeSourceRecycler.adapter =
|
||||
binding.mediaSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, chapterAdapter)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
@ -214,8 +214,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
reload()
|
||||
}
|
||||
} else {
|
||||
binding.animeNotSupported.visibility = View.VISIBLE
|
||||
binding.animeNotSupported.text =
|
||||
binding.mediaNotSupported.visibility = View.VISIBLE
|
||||
binding.mediaNotSupported.text =
|
||||
getString(R.string.not_supported, media.format ?: "")
|
||||
}
|
||||
}
|
||||
|
@ -231,10 +231,10 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
|
||||
fun multiDownload(n: Int) {
|
||||
//get last viewed chapter
|
||||
// Get last viewed chapter
|
||||
val selected = media.userProgress
|
||||
val chapters = media.manga?.chapters?.values?.toList()
|
||||
//filter by selected language
|
||||
// Filter by selected language
|
||||
val progressChapterIndex = (chapters?.indexOfFirst {
|
||||
MediaNameAdapter.findChapterNumber(it.number)?.toInt() == selected
|
||||
} ?: 0) + 1
|
||||
|
@ -244,7 +244,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
// Calculate the end index
|
||||
val endIndex = minOf(progressChapterIndex + n, chapters.size)
|
||||
|
||||
//make sure there are enough chapters
|
||||
// Make sure there are enough chapters
|
||||
val chaptersToDownload = chapters.subList(progressChapterIndex, endIndex)
|
||||
|
||||
|
||||
|
@ -386,32 +386,30 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
if (allSettings.size > 1) {
|
||||
val names =
|
||||
allSettings.map { LanguageMapper.getLanguageName(it.lang) }.toTypedArray()
|
||||
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, -1) { dialog, which ->
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Select a Source")
|
||||
singleChoiceItems(names) { which ->
|
||||
selectedSetting = allSettings[which]
|
||||
itemSelected = true
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
val fragment =
|
||||
MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadChapters(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadChapters(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismiss{
|
||||
if (!itemSelected) {
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
|
||||
}
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
|
@ -584,7 +582,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
private fun reload() {
|
||||
val selected = model.loadSelected(media)
|
||||
|
||||
//Find latest chapter for subscription
|
||||
// Find latest chapter for subscription
|
||||
selected.latest =
|
||||
media.manga?.chapters?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest =
|
||||
|
@ -618,14 +616,14 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.mediaInfoProgressBar.visibility = progress
|
||||
binding.animeSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
binding.mediaSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
|
||||
requireActivity().setNavigationTheme()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
state = binding.animeSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
state = binding.mediaSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -83,6 +83,7 @@ import ani.dantotsu.showSystemBarsRetractView
|
|||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.tryWith
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.alexvasilkov.gestures.views.GestureFrameLayout
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
|
@ -1013,28 +1014,27 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
PrefManager.setCustomVal("${media.id}_progressDialog", !isChecked)
|
||||
showProgressDialog = !isChecked
|
||||
}
|
||||
AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.title_update_progress))
|
||||
.setView(dialogView)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(getString(R.string.yes)) { dialog, _ ->
|
||||
customAlertDialog().apply {
|
||||
setTitle(R.string.title_update_progress)
|
||||
setCustomView(dialogView)
|
||||
setCancelable(false)
|
||||
setPosButton(R.string.yes) {
|
||||
PrefManager.setCustomVal("${media.id}_save_progress", true)
|
||||
updateProgress(
|
||||
media,
|
||||
MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
.toString()
|
||||
)
|
||||
dialog.dismiss()
|
||||
runnable.run()
|
||||
}
|
||||
.setNegativeButton(getString(R.string.no)) { dialog, _ ->
|
||||
setNegButton(R.string.no) {
|
||||
PrefManager.setCustomVal("${media.id}_save_progress", false)
|
||||
dialog.dismiss()
|
||||
runnable.run()
|
||||
}
|
||||
.setOnCancelListener { hideSystemBars() }
|
||||
.create()
|
||||
.show()
|
||||
setOnCancelListener { hideSystemBars() }
|
||||
show()
|
||||
|
||||
}
|
||||
} else {
|
||||
if (!incognito && PrefManager.getCustomVal(
|
||||
"${media.id}_save_progress",
|
||||
|
|
|
@ -50,16 +50,16 @@ class NovelReadAdapter(
|
|||
val source =
|
||||
media.selected!!.sourceIndex.let { if (it >= novelReadSources.names.size) 0 else it }
|
||||
if (novelReadSources.names.isNotEmpty() && source in 0 until novelReadSources.names.size) {
|
||||
binding.animeSource.setText(novelReadSources.names[source], false)
|
||||
binding.mediaSource.setText(novelReadSources.names[source], false)
|
||||
}
|
||||
binding.animeSource.setAdapter(
|
||||
binding.mediaSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
novelReadSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i)
|
||||
search()
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import androidx.recyclerview.widget.ConcatAdapter
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.FragmentMediaSourceBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.novel.NovelDownloaderService
|
||||
|
@ -47,7 +47,7 @@ class NovelReadFragment : Fragment(),
|
|||
DownloadTriggerCallback,
|
||||
DownloadedCheckCallback {
|
||||
|
||||
private var _binding: FragmentAnimeWatchBinding? = null
|
||||
private var _binding: FragmentMediaSourceBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val model: MediaDetailsViewModel by activityViewModels()
|
||||
|
||||
|
@ -214,11 +214,11 @@ class NovelReadFragment : Fragment(),
|
|||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
|
||||
binding.mediaSourceRecycler.updatePadding(bottom = binding.mediaSourceRecycler.paddingBottom + navBarHeight)
|
||||
|
||||
binding.animeSourceRecycler.layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.mediaSourceRecycler.layoutManager = LinearLayoutManager(requireContext())
|
||||
model.scrolledToTop.observe(viewLifecycleOwner) {
|
||||
if (it) binding.animeSourceRecycler.scrollToPosition(0)
|
||||
if (it) binding.mediaSourceRecycler.scrollToPosition(0)
|
||||
}
|
||||
|
||||
continueEp = model.continueMedia ?: false
|
||||
|
@ -237,7 +237,7 @@ class NovelReadFragment : Fragment(),
|
|||
this,
|
||||
this
|
||||
) // probably a better way to do this but it works
|
||||
binding.animeSourceRecycler.adapter =
|
||||
binding.mediaSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, novelResponseAdapter)
|
||||
loaded = true
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
|
@ -290,7 +290,7 @@ class NovelReadFragment : Fragment(),
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentAnimeWatchBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentMediaSourceBinding.inflate(inflater, container, false)
|
||||
return _binding?.root
|
||||
}
|
||||
|
||||
|
@ -304,12 +304,12 @@ class NovelReadFragment : Fragment(),
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.mediaInfoProgressBar.visibility = progress
|
||||
binding.animeSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
binding.mediaSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
state = binding.animeSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
state = binding.mediaSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -13,6 +13,7 @@ import ani.dantotsu.parsers.ShowResponse
|
|||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
|
||||
|
@ -38,7 +39,7 @@ class NovelResponseAdapter(
|
|||
val binding = holder.binding
|
||||
val novel = list[position]
|
||||
setAnimation(fragment.requireContext(), holder.binding.root)
|
||||
binding.itemEpisodeImage.loadImage(novel.coverUrl, 400, 0)
|
||||
binding.itemMediaImage.loadImage(novel.coverUrl, 400, 0)
|
||||
|
||||
val color =fragment.requireContext().getThemeColor(com.google.android.material.R.attr.colorOnBackground)
|
||||
binding.itemEpisodeTitle.text = novel.name
|
||||
|
@ -93,27 +94,22 @@ class NovelResponseAdapter(
|
|||
}
|
||||
|
||||
binding.root.setOnLongClickListener {
|
||||
val builder = androidx.appcompat.app.AlertDialog.Builder(
|
||||
fragment.requireContext(),
|
||||
R.style.MyPopup
|
||||
)
|
||||
builder.setTitle("Delete ${novel.name}?")
|
||||
builder.setMessage("Are you sure you want to delete ${novel.name}?")
|
||||
builder.setPositiveButton("Yes") { _, _ ->
|
||||
downloadedCheckCallback.deleteDownload(novel)
|
||||
deleteDownload(novel.link)
|
||||
snackString("Deleted ${novel.name}")
|
||||
if (binding.itemEpisodeFiller.text.toString()
|
||||
.contains("Download", ignoreCase = true)
|
||||
) {
|
||||
binding.itemEpisodeFiller.text = ""
|
||||
it.context.customAlertDialog().apply {
|
||||
setTitle("Delete ${novel.name}?")
|
||||
setMessage("Are you sure you want to delete ${novel.name}?")
|
||||
setPosButton(R.string.yes) {
|
||||
downloadedCheckCallback.deleteDownload(novel)
|
||||
deleteDownload(novel.link)
|
||||
snackString("Deleted ${novel.name}")
|
||||
if (binding.itemEpisodeFiller.text.toString()
|
||||
.contains("Download", ignoreCase = true)
|
||||
) {
|
||||
binding.itemEpisodeFiller.text = ""
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.no)
|
||||
show()
|
||||
}
|
||||
builder.setNegativeButton("No") { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ class ListActivity : AppCompatActivity() {
|
|||
|
||||
window.statusBarColor = primaryColor
|
||||
window.navigationBarColor = primaryColor
|
||||
binding.listed.visibility = View.GONE
|
||||
binding.listTabLayout.setBackgroundColor(primaryColor)
|
||||
binding.listAppBar.setBackgroundColor(primaryColor)
|
||||
binding.listTitle.setTextColor(primaryTextColor)
|
||||
|
|
|
@ -39,7 +39,7 @@ object AnimeSources : WatchSources() {
|
|||
}
|
||||
|
||||
fun performReorderAnimeSources() {
|
||||
//remove the downloaded source from the list to avoid duplicates
|
||||
// Remove the downloaded source from the list to avoid duplicates
|
||||
list = list.filter { it.name != "Downloaded" }
|
||||
list = sortPinnedAnimeSources(list, pinnedAnimeSources) + Lazier(
|
||||
{ OfflineAnimeParser() },
|
||||
|
|
|
@ -38,7 +38,6 @@ import ani.dantotsu.snackString
|
|||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
|
@ -19,8 +19,7 @@ import ani.dantotsu.databinding.FragmentFeedBinding
|
|||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.setBaseline
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import eu.kanade.tachiyomi.util.system.getSerializableCompat
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -44,30 +43,16 @@ class ActivityFragment : Fragment() {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
type = arguments?.getSerializableCompat<ActivityType>("type") as ActivityType
|
||||
userId = arguments?.getInt("userId")
|
||||
activityId = arguments?.getInt("activityId")
|
||||
binding.titleBar.visibility = if (type == ActivityType.OTHER_USER) View.VISIBLE else View.GONE
|
||||
binding.titleText.text = if (userId == Anilist.userid) getString(R.string.create_new_activity) else getString(R.string.write_a_message)
|
||||
binding.titleImage.setOnClickListener {
|
||||
if(userId == Anilist.userid) {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(),
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
.putExtra("type", "activity"),
|
||||
null
|
||||
)
|
||||
} else{
|
||||
ContextCompat.startActivity(
|
||||
requireContext(),
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
.putExtra("type", "message")
|
||||
.putExtra("userId", userId),
|
||||
|
||||
null
|
||||
)
|
||||
}
|
||||
arguments?.let {
|
||||
type = it.getSerializableCompat<ActivityType>("type") as ActivityType
|
||||
userId = it.getInt("userId")
|
||||
activityId = it.getInt("activityId")
|
||||
}
|
||||
binding.titleBar.visibility =
|
||||
if (type == ActivityType.OTHER_USER) View.VISIBLE else View.GONE
|
||||
binding.titleText.text =
|
||||
if (userId == Anilist.userid) getString(R.string.create_new_activity) else getString(R.string.write_a_message)
|
||||
binding.titleImage.setOnClickListener { handleTitleImageClick() }
|
||||
binding.listRecyclerView.adapter = adapter
|
||||
binding.listRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
binding.listProgressBar.isVisible = true
|
||||
|
@ -106,6 +91,13 @@ class ActivityFragment : Fragment() {
|
|||
})
|
||||
}
|
||||
|
||||
private fun handleTitleImageClick() {
|
||||
val intent = Intent(context, ActivityMarkdownCreator::class.java).apply {
|
||||
putExtra("type", if (userId == Anilist.userid) "activity" else "message")
|
||||
putExtra("userId", userId)
|
||||
}
|
||||
ContextCompat.startActivity(requireContext(), intent, null)
|
||||
}
|
||||
|
||||
private suspend fun getList() {
|
||||
val list = when (type) {
|
||||
|
@ -114,14 +106,14 @@ class ActivityFragment : Fragment() {
|
|||
ActivityType.OTHER_USER -> getActivities(userId = userId)
|
||||
ActivityType.ONE -> getActivities(activityId = activityId)
|
||||
}
|
||||
adapter.addAll(list.map { ActivityItem(it, ::onActivityClick, adapter ,requireActivity()) })
|
||||
adapter.addAll(list.map { ActivityItem(it, adapter, ::onActivityClick) })
|
||||
}
|
||||
|
||||
private suspend fun getActivities(
|
||||
global: Boolean = false,
|
||||
userId: Int? = null,
|
||||
activityId: Int? = null,
|
||||
filter:Boolean = false
|
||||
filter: Boolean = false
|
||||
): List<Activity> {
|
||||
val res = Anilist.query.getFeed(userId, global, page, activityId)?.data?.page?.activities
|
||||
page += 1
|
||||
|
@ -142,37 +134,33 @@ class ActivityFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun onActivityClick(id: Int, type: String) {
|
||||
when (type) {
|
||||
"USER" -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), ProfileActivity::class.java)
|
||||
.putExtra("userId", id), null
|
||||
)
|
||||
}
|
||||
val intent = when (type) {
|
||||
"USER" -> Intent(requireContext(), ProfileActivity::class.java).putExtra("userId", id)
|
||||
"MEDIA" -> Intent(
|
||||
requireContext(),
|
||||
MediaDetailsActivity::class.java
|
||||
).putExtra("mediaId", id)
|
||||
|
||||
"MEDIA" -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), MediaDetailsActivity::class.java)
|
||||
.putExtra("mediaId", id), null
|
||||
)
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
ContextCompat.startActivity(requireContext(), intent, null)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (this::binding.isInitialized) {
|
||||
binding.root.requestLayout()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
enum class ActivityType {
|
||||
GLOBAL, USER, OTHER_USER, ONE
|
||||
}
|
||||
enum class ActivityType { GLOBAL, USER, OTHER_USER, ONE }
|
||||
|
||||
fun newInstance(type: ActivityType, userId: Int? = null, activityId: Int? = null): ActivityFragment {
|
||||
fun newInstance(
|
||||
type: ActivityType,
|
||||
userId: Int? = null,
|
||||
activityId: Int? = null
|
||||
): ActivityFragment {
|
||||
return ActivityFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable("type", type)
|
||||
|
|
|
@ -5,21 +5,19 @@ import android.view.View
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
import ani.dantotsu.buildMarkwon
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.anilist.api.Activity
|
||||
import ani.dantotsu.databinding.ItemActivityBinding
|
||||
import ani.dantotsu.home.status.RepliesBottomDialog
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.profile.User
|
||||
import ani.dantotsu.profile.UsersDialogFragment
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -30,9 +28,8 @@ import kotlinx.coroutines.withContext
|
|||
|
||||
class ActivityItem(
|
||||
private val activity: Activity,
|
||||
val clickCallback: (Int, type: String) -> Unit,
|
||||
private val parentAdapter: GroupieAdapter,
|
||||
private val fragActivity: FragmentActivity
|
||||
val clickCallback: (Int, type: String) -> Unit,
|
||||
) : BindableItem<ItemActivityBinding>() {
|
||||
private lateinit var binding: ItemActivityBinding
|
||||
|
||||
|
@ -55,14 +52,14 @@ class ActivityItem(
|
|||
}
|
||||
binding.activityRepliesContainer.setOnClickListener {
|
||||
RepliesBottomDialog.newInstance(activity.id)
|
||||
.show(fragActivity.supportFragmentManager, "replies")
|
||||
.show((context as FragmentActivity).supportFragmentManager, "replies")
|
||||
}
|
||||
binding.replyCount.text = activity.replyCount.toString()
|
||||
binding.activityReplies.setColorFilter(ContextCompat.getColor(binding.root.context, R.color.bg_opp))
|
||||
binding.activityLikeContainer.setOnLongClickListener {
|
||||
UsersDialogFragment().apply {
|
||||
userList(userList)
|
||||
show(fragActivity.supportFragmentManager, "dialog")
|
||||
show((context as FragmentActivity).supportFragmentManager, "dialog")
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -152,7 +149,7 @@ class ActivityItem(
|
|||
binding.activityEdit.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "activity")
|
||||
.putExtra("other", activity.text)
|
||||
.putExtra("edit", activity.id),
|
||||
|
@ -183,7 +180,7 @@ class ActivityItem(
|
|||
binding.activityEdit.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "message")
|
||||
.putExtra("other", activity.message)
|
||||
.putExtra("edit", activity.id)
|
||||
|
|
|
@ -15,7 +15,7 @@ import ani.dantotsu.profile.User
|
|||
import ani.dantotsu.profile.UsersDialogFragment
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -81,7 +81,7 @@ class ActivityReplyItem(
|
|||
binding.activityReply.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "replyActivity")
|
||||
.putExtra("parentId", parentId)
|
||||
.putExtra("other", "@${reply.user.name} "),
|
||||
|
@ -92,7 +92,7 @@ class ActivityReplyItem(
|
|||
binding.activityEdit.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "replyActivity")
|
||||
.putExtra("parentId", parentId)
|
||||
.putExtra("other", reply.text)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package ani.dantotsu.home.status
|
||||
package ani.dantotsu.profile.activity
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
|
@ -14,12 +14,10 @@ import ani.dantotsu.connections.anilist.Anilist
|
|||
import ani.dantotsu.connections.anilist.api.ActivityReply
|
||||
import ani.dantotsu.databinding.BottomSheetRecyclerBinding
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.profile.activity.ActivityReplyItem
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
@ -50,7 +48,7 @@ class RepliesBottomDialog : BottomSheetDialogFragment() {
|
|||
binding.replyButton.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "replyActivity")
|
||||
.putExtra("parentId", activityId),
|
||||
null
|
||||
|
@ -73,14 +71,10 @@ class RepliesBottomDialog : BottomSheetDialogFragment() {
|
|||
adapter.update(
|
||||
replies.map {
|
||||
ActivityReplyItem(
|
||||
it,
|
||||
activityId,
|
||||
requireActivity(),
|
||||
adapter,
|
||||
clickCallback = { int, _ ->
|
||||
onClick(int)
|
||||
}
|
||||
)
|
||||
it, activityId, requireActivity(), adapter,
|
||||
) { i, _ ->
|
||||
onClick(i)
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
|
@ -20,7 +20,7 @@ import ani.dantotsu.profile.notification.NotificationFragment.Companion.Notifica
|
|||
import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||
|
||||
class NotificationActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityNotificationBinding
|
||||
lateinit var binding: ActivityNotificationBinding
|
||||
private var selected: Int = 0
|
||||
lateinit var navBar: AnimatedBottomBar
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -38,8 +38,8 @@ class NotificationActivity : AppCompatActivity() {
|
|||
bottomMargin = navBarHeight
|
||||
}
|
||||
val tabs = listOf(
|
||||
Pair(R.drawable.ic_round_movie_filter_24, "Media"),
|
||||
Pair(R.drawable.ic_round_person_24, "User"),
|
||||
Pair(R.drawable.ic_round_movie_filter_24, "Media"),
|
||||
Pair(R.drawable.ic_round_notifications_active_24, "Subs"),
|
||||
Pair(R.drawable.ic_round_comment_24, "Comments")
|
||||
)
|
||||
|
@ -49,7 +49,6 @@ class NotificationActivity : AppCompatActivity() {
|
|||
val getOne = intent.getIntExtra("activityId", -1)
|
||||
if (getOne != -1) navBar.isVisible = false
|
||||
binding.notificationViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, getOne)
|
||||
binding.notificationViewPager.setOffscreenPageLimit(4)
|
||||
binding.notificationViewPager.setCurrentItem(selected, false)
|
||||
navBar.selectTabAt(selected)
|
||||
navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener {
|
||||
|
@ -84,8 +83,8 @@ class NotificationActivity : AppCompatActivity() {
|
|||
override fun getItemCount(): Int = if (id != -1) 1 else 4
|
||||
|
||||
override fun createFragment(position: Int): Fragment = when (position) {
|
||||
0 -> NotificationFragment.newInstance(if (id != -1) NotificationType.ONE else NotificationType.MEDIA, id)
|
||||
1 -> NotificationFragment.newInstance(NotificationType.USER)
|
||||
0 -> NotificationFragment.newInstance(NotificationType.USER)
|
||||
1 -> NotificationFragment.newInstance(if (id != -1) NotificationType.ONE else NotificationType.MEDIA, id)
|
||||
2 -> NotificationFragment.newInstance(NotificationType.SUBSCRIPTION)
|
||||
3 -> NotificationFragment.newInstance(NotificationType.COMMENT)
|
||||
else -> NotificationFragment.newInstance(NotificationType.MEDIA)
|
||||
|
|
|
@ -46,8 +46,10 @@ class NotificationFragment : Fragment() {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
type = arguments?.getSerializableCompat<NotificationType>("type") as NotificationType
|
||||
getID = arguments?.getInt("id") ?: -1
|
||||
arguments?.let {
|
||||
getID = it.getInt("id")
|
||||
type = it.getSerializableCompat<NotificationType>("type") as NotificationType
|
||||
}
|
||||
binding.notificationRecyclerView.adapter = adapter
|
||||
binding.notificationRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
binding.notificationProgressBar.isVisible = true
|
||||
|
@ -158,47 +160,31 @@ class NotificationFragment : Fragment() {
|
|||
!binding.notificationRecyclerView.canScrollVertically(1)
|
||||
}
|
||||
|
||||
fun onClick(
|
||||
id: Int,
|
||||
optional: Int?,
|
||||
type: NotificationClickType
|
||||
) {
|
||||
when (type) {
|
||||
NotificationClickType.USER -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), ProfileActivity::class.java)
|
||||
.putExtra("userId", id), null
|
||||
)
|
||||
fun onClick(id: Int, optional: Int?, type: NotificationClickType) {
|
||||
val intent = when (type) {
|
||||
NotificationClickType.USER -> Intent(requireContext(), ProfileActivity::class.java).apply {
|
||||
putExtra("userId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.MEDIA -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), MediaDetailsActivity::class.java)
|
||||
.putExtra("mediaId", id), null
|
||||
)
|
||||
NotificationClickType.MEDIA -> Intent(requireContext(), MediaDetailsActivity::class.java).apply {
|
||||
putExtra("mediaId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.ACTIVITY -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), FeedActivity::class.java)
|
||||
.putExtra("activityId", id), null
|
||||
)
|
||||
NotificationClickType.ACTIVITY -> Intent(requireContext(), FeedActivity::class.java).apply {
|
||||
putExtra("activityId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.COMMENT -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), MediaDetailsActivity::class.java)
|
||||
.putExtra("FRAGMENT_TO_LOAD", "COMMENTS")
|
||||
.putExtra("mediaId", id)
|
||||
.putExtra("commentId", optional ?: -1),
|
||||
null
|
||||
)
|
||||
|
||||
NotificationClickType.COMMENT -> Intent(requireContext(), MediaDetailsActivity::class.java).apply {
|
||||
putExtra("FRAGMENT_TO_LOAD", "COMMENTS")
|
||||
putExtra("mediaId", id)
|
||||
putExtra("commentId", optional ?: -1)
|
||||
}
|
||||
|
||||
NotificationClickType.UNDEFINED -> {
|
||||
// Do nothing
|
||||
}
|
||||
NotificationClickType.UNDEFINED -> null
|
||||
}
|
||||
|
||||
intent?.let {
|
||||
ContextCompat.startActivity(requireContext(), it, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,18 +192,12 @@ class NotificationFragment : Fragment() {
|
|||
super.onResume()
|
||||
if (this::binding.isInitialized) {
|
||||
binding.root.requestLayout()
|
||||
binding.root.setBaseline((activity as NotificationActivity).navBar)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
enum class NotificationClickType {
|
||||
USER, MEDIA, ACTIVITY, COMMENT, UNDEFINED
|
||||
}
|
||||
|
||||
enum class NotificationType {
|
||||
MEDIA, USER, SUBSCRIPTION, COMMENT, ONE
|
||||
}
|
||||
enum class NotificationClickType { USER, MEDIA, ACTIVITY, COMMENT, UNDEFINED }
|
||||
enum class NotificationType { MEDIA, USER, SUBSCRIPTION, COMMENT, ONE }
|
||||
|
||||
fun newInstance(type: NotificationType, id: Int = -1): NotificationFragment {
|
||||
return NotificationFragment().apply {
|
||||
|
|
|
@ -35,6 +35,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
|
@ -178,25 +179,20 @@ class ExtensionsActivity : AppCompatActivity() {
|
|||
entry.name.lowercase().replace("_", " ")
|
||||
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() }
|
||||
}.toTypedArray()
|
||||
val builder = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
val listOrder: String = PrefManager.getVal(PrefName.LangSort)
|
||||
val index = LanguageMapper.Companion.Language.entries.toTypedArray()
|
||||
.indexOfFirst { it.code == listOrder }
|
||||
builder.setTitle("Language")
|
||||
builder.setSingleChoiceItems(languageOptions, index) { dialog, i ->
|
||||
PrefManager.setVal(
|
||||
PrefName.LangSort,
|
||||
LanguageMapper.Companion.Language.entries[i].code
|
||||
)
|
||||
val currentFragment =
|
||||
supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
|
||||
if (currentFragment is SearchQueryHandler) {
|
||||
currentFragment.notifyDataChanged()
|
||||
customAlertDialog().apply {
|
||||
setTitle("Language")
|
||||
singleChoiceItems(languageOptions, index) { selected ->
|
||||
PrefManager.setVal(PrefName.LangSort, LanguageMapper.Companion.Language.entries[selected].code)
|
||||
val currentFragment = supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
|
||||
if (currentFragment is SearchQueryHandler) {
|
||||
currentFragment.notifyDataChanged()
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
show()
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
binding.settingsContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = statusBarHeight
|
||||
|
@ -247,10 +243,10 @@ class ExtensionsActivity : AppCompatActivity() {
|
|||
)
|
||||
view.repositoryItem.text = item.removePrefix("https://raw.githubusercontent.com")
|
||||
view.repositoryItem.setOnClickListener {
|
||||
AlertDialog.Builder(this@ExtensionsActivity, R.style.MyPopup)
|
||||
.setTitle(R.string.rem_repository)
|
||||
.setMessage(item)
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
customAlertDialog().apply {
|
||||
setTitle(R.string.rem_repository)
|
||||
setMessage(item)
|
||||
setPosButton(R.string.ok) {
|
||||
val repos = PrefManager.getVal<Set<String>>(prefName).minus(item)
|
||||
PrefManager.setVal(prefName, repos)
|
||||
repoInventory.removeView(view.root)
|
||||
|
@ -267,13 +263,10 @@ class ExtensionsActivity : AppCompatActivity() {
|
|||
else -> {}
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
.show()
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
view.repositoryItem.setOnLongClickListener {
|
||||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
|
@ -324,20 +317,18 @@ class ExtensionsActivity : AppCompatActivity() {
|
|||
dialogView.repoInventory.apply {
|
||||
getSavedRepositories(this, type)
|
||||
}
|
||||
val alertDialog = AlertDialog.Builder(this@ExtensionsActivity, R.style.MyPopup)
|
||||
.setTitle(R.string.edit_repositories)
|
||||
.setView(dialogView.root)
|
||||
.setPositiveButton(getString(R.string.add)) { _, _ ->
|
||||
if (!dialogView.repositoryTextBox.text.isNullOrBlank())
|
||||
processUserInput(dialogView.repositoryTextBox.text.toString(), type)
|
||||
}
|
||||
.setNegativeButton(getString(R.string.close)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
processEditorAction(dialogView.repositoryTextBox, type)
|
||||
alertDialog.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(R.string.edit_repositories)
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.add) {
|
||||
if (!dialogView.repositoryTextBox.text.isNullOrBlank()) {
|
||||
processUserInput(dialogView.repositoryTextBox.text.toString(), type)
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.close)
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,11 @@ class FAQActivity : AppCompatActivity() {
|
|||
currContext()?.getString(R.string.question_5) ?: "",
|
||||
currContext()?.getString(R.string.answer_5) ?: ""
|
||||
),
|
||||
Triple(
|
||||
R.drawable.ic_anilist,
|
||||
currContext()?.getString(R.string.question_18) ?: "",
|
||||
currContext()?.getString(R.string.answer_18) ?: ""
|
||||
),
|
||||
Triple(
|
||||
R.drawable.ic_anilist,
|
||||
currContext()?.getString(R.string.question_6) ?: "",
|
||||
|
@ -60,6 +65,11 @@ class FAQActivity : AppCompatActivity() {
|
|||
currContext()?.getString(R.string.question_7) ?: "",
|
||||
currContext()?.getString(R.string.answer_7) ?: ""
|
||||
),
|
||||
Triple(
|
||||
R.drawable.ic_round_magnet_24,
|
||||
currContext()?.getString(R.string.question_19) ?: "",
|
||||
currContext()?.getString(R.string.answer_19) ?: ""
|
||||
),
|
||||
Triple(
|
||||
R.drawable.ic_round_lock_open_24,
|
||||
currContext()?.getString(R.string.question_9) ?: "",
|
||||
|
|
|
@ -25,13 +25,15 @@ import androidx.viewpager2.widget.ViewPager2
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.databinding.FragmentExtensionsBinding
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
import ani.dantotsu.others.LanguageMapper.Companion.getLanguageName
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
|
@ -72,16 +74,15 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
if (allSettings.isNotEmpty()) {
|
||||
var selectedSetting = allSettings[0]
|
||||
if (allSettings.size > 1) {
|
||||
val names = allSettings.map { LanguageMapper.getLanguageName(it.lang) }
|
||||
val names = allSettings.map { getLanguageName(it.lang) }
|
||||
.toTypedArray()
|
||||
var selectedIndex = 0
|
||||
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, selectedIndex) { dialog, which ->
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Select a Source")
|
||||
singleChoiceItems(names, selectedIndex) { which ->
|
||||
itemSelected = true
|
||||
selectedIndex = which
|
||||
selectedSetting = allSettings[selectedIndex]
|
||||
dialog.dismiss()
|
||||
|
||||
val fragment =
|
||||
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
|
@ -93,13 +94,13 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismiss {
|
||||
if (!itemSelected) {
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment =
|
||||
|
@ -295,7 +296,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val extension = getItem(position)
|
||||
val nsfw = if (extension.isNsfw) "(18+)" else ""
|
||||
val lang = LanguageMapper.getLanguageName(extension.lang)
|
||||
val lang = getLanguageName(extension.lang)
|
||||
holder.extensionNameTextView.text = extension.name
|
||||
val versionText = "$lang ${extension.versionName} $nsfw"
|
||||
holder.extensionVersionTextView.text = versionText
|
||||
|
|
|
@ -34,6 +34,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
|
@ -74,13 +75,12 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
val names = allSettings.map { LanguageMapper.getLanguageName(it.lang) }
|
||||
.toTypedArray()
|
||||
var selectedIndex = 0
|
||||
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, selectedIndex) { dialog, which ->
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Select a Source")
|
||||
singleChoiceItems(names, selectedIndex) { which ->
|
||||
itemSelected = true
|
||||
selectedIndex = which
|
||||
selectedSetting = allSettings[selectedIndex]
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
val fragment =
|
||||
|
@ -93,13 +93,13 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismiss {
|
||||
if (!itemSelected) {
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment =
|
||||
|
|
|
@ -28,6 +28,7 @@ import ani.dantotsu.snackString
|
|||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.slider.Slider.OnChangeListener
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
@ -100,20 +101,19 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
R.string.default_playback_speed,
|
||||
speedsName[PrefManager.getVal(PrefName.DefaultSpeed)]
|
||||
)
|
||||
val speedDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.default_speed))
|
||||
binding.playerSettingsSpeed.setOnClickListener {
|
||||
val dialog =
|
||||
speedDialog.setSingleChoiceItems(
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.default_speed))
|
||||
singleChoiceItems(
|
||||
speedsName,
|
||||
PrefManager.getVal(PrefName.DefaultSpeed)
|
||||
) { dialog, i ->
|
||||
) { i ->
|
||||
PrefManager.setVal(PrefName.DefaultSpeed, i)
|
||||
binding.playerSettingsSpeed.text =
|
||||
getString(R.string.default_playback_speed, speedsName[i])
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
binding.playerSettingsCursedSpeeds.isChecked = PrefManager.getVal(PrefName.CursedSpeeds)
|
||||
|
@ -278,17 +278,17 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
val resizeModes = arrayOf("Original", "Zoom", "Stretch")
|
||||
val resizeDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.default_resize_mode))
|
||||
binding.playerResizeMode.setOnClickListener {
|
||||
val dialog = resizeDialog.setSingleChoiceItems(
|
||||
resizeModes,
|
||||
PrefManager.getVal<Int>(PrefName.Resize)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.Resize, count)
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.default_resize_mode))
|
||||
singleChoiceItems(
|
||||
resizeModes,
|
||||
PrefManager.getVal<Int>(PrefName.Resize)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.Resize, count)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleSubOptions(isChecked: Boolean) {
|
||||
|
@ -332,18 +332,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Blue",
|
||||
"Magenta"
|
||||
)
|
||||
val primaryColorDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.primary_sub_color))
|
||||
binding.videoSubColorPrimary.setOnClickListener {
|
||||
val dialog = primaryColorDialog.setSingleChoiceItems(
|
||||
colorsPrimary,
|
||||
PrefManager.getVal(PrefName.PrimaryColor)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.PrimaryColor, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.primary_sub_color))
|
||||
singleChoiceItems(
|
||||
colorsPrimary,
|
||||
PrefManager.getVal(PrefName.PrimaryColor)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.PrimaryColor, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
val colorsSecondary = arrayOf(
|
||||
"Black",
|
||||
|
@ -359,32 +359,32 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Magenta",
|
||||
"Transparent"
|
||||
)
|
||||
val secondaryColorDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.outline_sub_color))
|
||||
binding.videoSubColorSecondary.setOnClickListener {
|
||||
val dialog = secondaryColorDialog.setSingleChoiceItems(
|
||||
colorsSecondary,
|
||||
PrefManager.getVal(PrefName.SecondaryColor)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.SecondaryColor, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.outline_sub_color))
|
||||
singleChoiceItems(
|
||||
colorsSecondary,
|
||||
PrefManager.getVal(PrefName.SecondaryColor)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.SecondaryColor, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
val typesOutline = arrayOf("Outline", "Shine", "Drop Shadow", "None")
|
||||
val outlineDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.outline_type))
|
||||
binding.videoSubOutline.setOnClickListener {
|
||||
val dialog = outlineDialog.setSingleChoiceItems(
|
||||
typesOutline,
|
||||
PrefManager.getVal(PrefName.Outline)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.Outline, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.outline_type))
|
||||
singleChoiceItems(
|
||||
typesOutline,
|
||||
PrefManager.getVal(PrefName.Outline)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.Outline, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
val colorsSubBackground = arrayOf(
|
||||
"Transparent",
|
||||
|
@ -400,18 +400,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Blue",
|
||||
"Magenta"
|
||||
)
|
||||
val subBackgroundDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.sub_background_color_select))
|
||||
binding.videoSubColorBackground.setOnClickListener {
|
||||
val dialog = subBackgroundDialog.setSingleChoiceItems(
|
||||
colorsSubBackground,
|
||||
PrefManager.getVal(PrefName.SubBackground)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.SubBackground, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.sub_background_color_select))
|
||||
singleChoiceItems(
|
||||
colorsSubBackground,
|
||||
PrefManager.getVal(PrefName.SubBackground)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.SubBackground, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
val colorsSubWindow = arrayOf(
|
||||
|
@ -428,18 +428,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Blue",
|
||||
"Magenta"
|
||||
)
|
||||
val subWindowDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.sub_window_color_select))
|
||||
binding.videoSubColorWindow.setOnClickListener {
|
||||
val dialog = subWindowDialog.setSingleChoiceItems(
|
||||
colorsSubWindow,
|
||||
PrefManager.getVal(PrefName.SubWindow)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.SubWindow, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.sub_window_color_select))
|
||||
singleChoiceItems(
|
||||
colorsSubWindow,
|
||||
PrefManager.getVal(PrefName.SubWindow)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.SubWindow, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
binding.videoSubAlpha.value = PrefManager.getVal(PrefName.SubAlpha)
|
||||
|
@ -459,18 +459,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Levenim MT Bold",
|
||||
"Blocky"
|
||||
)
|
||||
val fontDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.subtitle_font))
|
||||
binding.videoSubFont.setOnClickListener {
|
||||
val dialog = fontDialog.setSingleChoiceItems(
|
||||
fonts,
|
||||
PrefManager.getVal(PrefName.Font)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.Font, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.subtitle_font))
|
||||
singleChoiceItems(
|
||||
fonts,
|
||||
PrefManager.getVal(PrefName.Font)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.Font, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
binding.subtitleFontSize.setText(PrefManager.getVal<Int>(PrefName.FontSize).toString())
|
||||
binding.subtitleFontSize.setOnEditorActionListener { _, actionId, _ ->
|
||||
|
|
|
@ -20,6 +20,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.databinding.ActivitySettingsCommonBinding
|
||||
import ani.dantotsu.databinding.DialogSetPasswordBinding
|
||||
import ani.dantotsu.databinding.DialogUserAgentBinding
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.initActivity
|
||||
|
@ -37,6 +38,7 @@ import ani.dantotsu.themes.ThemeManager
|
|||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.LauncherWrapper
|
||||
import ani.dantotsu.util.StoragePermissions
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
|
@ -160,18 +162,16 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
icon = R.drawable.ic_download_24,
|
||||
onClick = {
|
||||
val managers = arrayOf("Default", "1DM", "ADM")
|
||||
val downloadManagerDialog =
|
||||
AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.download_manager)
|
||||
var downloadManager: Int = PrefManager.getVal(PrefName.DownloadManager)
|
||||
val dialog = downloadManagerDialog.setSingleChoiceItems(
|
||||
managers, downloadManager
|
||||
) { dialog, count ->
|
||||
downloadManager = count
|
||||
PrefManager.setVal(PrefName.DownloadManager, downloadManager)
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.download_manager))
|
||||
singleChoiceItems(
|
||||
managers,
|
||||
PrefManager.getVal(PrefName.DownloadManager)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.DownloadManager, count)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
|
@ -180,90 +180,67 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
desc = getString(R.string.app_lock_desc),
|
||||
icon = R.drawable.ic_round_lock_open_24,
|
||||
onClick = {
|
||||
val passwordDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.app_lock)
|
||||
.setView(R.layout.dialog_set_password)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ ->
|
||||
val passwordInput =
|
||||
(dialog as AlertDialog).findViewById<EditText>(R.id.passwordInput)
|
||||
val confirmPasswordInput =
|
||||
dialog.findViewById<EditText>(R.id.confirmPasswordInput)
|
||||
val forgotPasswordCheckbox =
|
||||
dialog.findViewById<CheckBox>(R.id.forgotPasswordCheckbox)
|
||||
if (forgotPasswordCheckbox?.isChecked == true) {
|
||||
customAlertDialog().apply {
|
||||
val view = DialogSetPasswordBinding.inflate(layoutInflater)
|
||||
setTitle(R.string.app_lock)
|
||||
setCustomView(view.root)
|
||||
setPosButton(R.string.ok) {
|
||||
if (view.forgotPasswordCheckbox.isChecked) {
|
||||
PrefManager.setVal(PrefName.OverridePassword, true)
|
||||
}
|
||||
|
||||
val password = passwordInput?.text.toString()
|
||||
val confirmPassword = confirmPasswordInput?.text.toString()
|
||||
|
||||
val password = view.passwordInput.text.toString()
|
||||
val confirmPassword = view.confirmPasswordInput.text.toString()
|
||||
if (password == confirmPassword && password.isNotEmpty()) {
|
||||
PrefManager.setVal(PrefName.AppPassword, password)
|
||||
if (dialog.findViewById<CheckBox>(R.id.biometricCheckbox)?.isChecked == true) {
|
||||
if (view.biometricCheckbox.isChecked) {
|
||||
val canBiometricPrompt =
|
||||
BiometricManager.from(applicationContext)
|
||||
.canAuthenticate(
|
||||
BiometricManager.Authenticators.BIOMETRIC_WEAK
|
||||
) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
|
||||
if (canBiometricPrompt) {
|
||||
val biometricPrompt =
|
||||
BiometricPromptUtils.createBiometricPrompt(
|
||||
this@SettingsCommonActivity
|
||||
) { _ ->
|
||||
BiometricPromptUtils.createBiometricPrompt(this@SettingsCommonActivity) { _ ->
|
||||
val token = UUID.randomUUID().toString()
|
||||
PrefManager.setVal(
|
||||
PrefName.BiometricToken,
|
||||
token
|
||||
)
|
||||
toast(R.string.success)
|
||||
dialog.dismiss()
|
||||
}
|
||||
val promptInfo =
|
||||
BiometricPromptUtils.createPromptInfo(
|
||||
this@SettingsCommonActivity
|
||||
)
|
||||
BiometricPromptUtils.createPromptInfo(this@SettingsCommonActivity)
|
||||
biometricPrompt.authenticate(promptInfo)
|
||||
}
|
||||
|
||||
} else {
|
||||
PrefManager.setVal(PrefName.BiometricToken, "")
|
||||
toast(R.string.success)
|
||||
dialog.dismiss()
|
||||
}
|
||||
} else {
|
||||
toast(R.string.password_mismatch)
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.remove) { dialog, _ ->
|
||||
setNegButton(R.string.cancel)
|
||||
setNeutralButton(R.string.remove){
|
||||
PrefManager.setVal(PrefName.AppPassword, "")
|
||||
PrefManager.setVal(PrefName.BiometricToken, "")
|
||||
PrefManager.setVal(PrefName.OverridePassword, false)
|
||||
toast(R.string.success)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
|
||||
passwordDialog.window?.setDimAmount(0.8f)
|
||||
passwordDialog.setOnShowListener {
|
||||
passwordDialog.findViewById<EditText>(R.id.passwordInput)
|
||||
?.requestFocus()
|
||||
val biometricCheckbox =
|
||||
passwordDialog.findViewById<CheckBox>(R.id.biometricCheckbox)
|
||||
val forgotPasswordCheckbox =
|
||||
passwordDialog.findViewById<CheckBox>(R.id.forgotPasswordCheckbox)
|
||||
val canAuthenticate =
|
||||
BiometricManager.from(applicationContext).canAuthenticate(
|
||||
BiometricManager.Authenticators.BIOMETRIC_WEAK
|
||||
) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
biometricCheckbox?.isVisible = canAuthenticate
|
||||
biometricCheckbox?.isChecked =
|
||||
PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty()
|
||||
forgotPasswordCheckbox?.isChecked =
|
||||
PrefManager.getVal(PrefName.OverridePassword)
|
||||
setOnShowListener {
|
||||
view.passwordInput.requestFocus()
|
||||
val canAuthenticate =
|
||||
BiometricManager.from(applicationContext).canAuthenticate(
|
||||
BiometricManager.Authenticators.BIOMETRIC_WEAK
|
||||
) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
view.biometricCheckbox.isVisible = canAuthenticate
|
||||
view.biometricCheckbox.isChecked =
|
||||
PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty()
|
||||
view.forgotPasswordCheckbox.isChecked =
|
||||
PrefManager.getVal(PrefName.OverridePassword)
|
||||
}
|
||||
show()
|
||||
}
|
||||
passwordDialog.show()
|
||||
}
|
||||
|
||||
),
|
||||
|
@ -328,10 +305,10 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
desc = getString(R.string.change_download_location_desc),
|
||||
icon = R.drawable.ic_round_source_24,
|
||||
onClick = {
|
||||
val dialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.change_download_location)
|
||||
.setMessage(R.string.download_location_msg)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ ->
|
||||
context.customAlertDialog().apply{
|
||||
setTitle(R.string.change_download_location)
|
||||
setMessage(R.string.download_location_msg)
|
||||
setPosButton(R.string.ok){
|
||||
val oldUri = PrefManager.getVal<String>(PrefName.DownloadsDir)
|
||||
launcher.registerForCallback { success ->
|
||||
if (success) {
|
||||
|
@ -354,12 +331,10 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
launcher.launch()
|
||||
dialog.dismiss()
|
||||
}.setNeutralButton(R.string.cancel) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.create()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
|
@ -372,6 +347,17 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
PrefManager.setVal(PrefName.ContinueMedia, isChecked)
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
type = 2,
|
||||
name = getString(R.string.hide_private),
|
||||
desc = getString(R.string.hide_private_desc),
|
||||
icon = R.drawable.ic_round_remove_red_eye_24,
|
||||
isChecked = PrefManager.getVal(PrefName.HidePrivate),
|
||||
switch = { isChecked, _ ->
|
||||
PrefManager.setVal(PrefName.HidePrivate, isChecked)
|
||||
restartApp()
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
type = 2,
|
||||
name = getString(R.string.search_source_list),
|
||||
|
|
|
@ -81,11 +81,11 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
|||
view.repositoryItem.text =
|
||||
item.removePrefix("https://raw.githubusercontent.com/")
|
||||
view.repositoryItem.setOnClickListener {
|
||||
AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.rem_repository).setMessage(item)
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
val repos =
|
||||
PrefManager.getVal<Set<String>>(repoList).minus(item)
|
||||
context.customAlertDialog().apply {
|
||||
setTitle(R.string.rem_repository)
|
||||
setMessage(item)
|
||||
setPosButton(R.string.ok) {
|
||||
val repos = PrefManager.getVal<Set<String>>(repoList).minus(item)
|
||||
PrefManager.setVal(repoList, repos)
|
||||
setExtensionOutput(repoInventory, type)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
|
@ -93,18 +93,16 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
|||
MediaType.ANIME -> {
|
||||
animeExtensionManager.findAvailableExtensions()
|
||||
}
|
||||
|
||||
MediaType.MANGA -> {
|
||||
mangaExtensionManager.findAvailableExtensions()
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
}.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.create().show()
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
view.repositoryItem.setOnLongClickListener {
|
||||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
|
@ -209,27 +207,27 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
|||
val editText = dialogView.userAgentTextBox.apply {
|
||||
hint = getString(R.string.manga_add_repository)
|
||||
}
|
||||
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.manga_add_repository).setView(dialogView.root)
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
context.customAlertDialog().apply {
|
||||
setTitle(R.string.manga_add_repository)
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.ok) {
|
||||
if (!editText.text.isNullOrBlank()) processUserInput(
|
||||
editText.text.toString(),
|
||||
MediaType.MANGA,
|
||||
it.attachView
|
||||
)
|
||||
dialog.dismiss()
|
||||
}.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.create()
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
attach { dialog ->
|
||||
processEditorAction(
|
||||
dialog,
|
||||
editText,
|
||||
MediaType.MANGA,
|
||||
it.attachView
|
||||
)
|
||||
}
|
||||
}.show()
|
||||
|
||||
processEditorAction(
|
||||
alertDialog,
|
||||
editText,
|
||||
MediaType.MANGA,
|
||||
it.attachView
|
||||
)
|
||||
alertDialog.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
},
|
||||
attach = {
|
||||
setExtensionOutput(it.attachView, MediaType.MANGA)
|
||||
|
@ -258,24 +256,18 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
|||
val dialogView = DialogUserAgentBinding.inflate(layoutInflater)
|
||||
val editText = dialogView.userAgentTextBox
|
||||
editText.setText(PrefManager.getVal<String>(PrefName.DefaultUserAgent))
|
||||
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.user_agent).setView(dialogView.root)
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
PrefManager.setVal(
|
||||
PrefName.DefaultUserAgent,
|
||||
editText.text.toString()
|
||||
)
|
||||
dialog.dismiss()
|
||||
}.setNeutralButton(getString(R.string.reset)) { dialog, _ ->
|
||||
context.customAlertDialog().apply {
|
||||
setTitle(R.string.user_agent)
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.ok) {
|
||||
PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString())
|
||||
}
|
||||
setNeutralButton(R.string.reset) {
|
||||
PrefManager.removeVal(PrefName.DefaultUserAgent)
|
||||
editText.setText("")
|
||||
dialog.dismiss()
|
||||
}.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.create()
|
||||
|
||||
alertDialog.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
}.show()
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
|
|
|
@ -25,6 +25,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import java.util.Locale
|
||||
|
||||
class SettingsNotificationActivity : AppCompatActivity() {
|
||||
|
@ -77,26 +78,16 @@ class SettingsNotificationActivity : AppCompatActivity() {
|
|||
desc = getString(R.string.subscriptions_info),
|
||||
icon = R.drawable.ic_round_notifications_none_24,
|
||||
onClick = {
|
||||
val speedDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.subscriptions_checking_time)
|
||||
val dialog =
|
||||
speedDialog.setSingleChoiceItems(timeNames, curTime) { dialog, i ->
|
||||
context.customAlertDialog().apply {
|
||||
setTitle(R.string.subscriptions_checking_time)
|
||||
singleChoiceItems(timeNames, curTime) { i ->
|
||||
curTime = i
|
||||
it.settingsTitle.text =
|
||||
getString(
|
||||
R.string.subscriptions_checking_time_s,
|
||||
timeNames[i]
|
||||
)
|
||||
PrefManager.setVal(
|
||||
PrefName.SubscriptionNotificationInterval,
|
||||
curTime
|
||||
)
|
||||
dialog.dismiss()
|
||||
TaskScheduler.create(
|
||||
context, PrefManager.getVal(PrefName.UseAlarmManager)
|
||||
).scheduleAllTasks(context)
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
it.settingsTitle.text = getString(R.string.subscriptions_checking_time_s, timeNames[i])
|
||||
PrefManager.setVal(PrefName.SubscriptionNotificationInterval, curTime)
|
||||
TaskScheduler.create(context, PrefManager.getVal(PrefName.UseAlarmManager)).scheduleAllTasks(context)
|
||||
}
|
||||
show()
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
TaskScheduler.create(
|
||||
|
|
|
@ -9,31 +9,25 @@ import ani.dantotsu.loadImage
|
|||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.Item
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
|
||||
class SubscriptionItem(
|
||||
val id: Int,
|
||||
private val media: SubscriptionHelper.Companion.SubscribeMedia,
|
||||
private val adapter: GroupieAdapter
|
||||
private val adapter: GroupieAdapter,
|
||||
private val onItemRemoved: (Int) -> Unit
|
||||
) : BindableItem<ItemSubscriptionBinding>() {
|
||||
private lateinit var binding: ItemSubscriptionBinding
|
||||
override fun bind(p0: ItemSubscriptionBinding, p1: Int) {
|
||||
val context = p0.root.context
|
||||
binding = p0
|
||||
val parserName = if (media.isAnime)
|
||||
SubscriptionHelper.getAnimeParser(media.id).name
|
||||
else
|
||||
SubscriptionHelper.getMangaParser(media.id).name
|
||||
val mediaName = media.name
|
||||
val showName = "$mediaName ($parserName)"
|
||||
binding.subscriptionName.text = showName
|
||||
|
||||
override fun bind(viewBinding: ItemSubscriptionBinding, position: Int) {
|
||||
binding = viewBinding
|
||||
val context = binding.root.context
|
||||
|
||||
binding.subscriptionName.text = media.name
|
||||
binding.root.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MediaDetailsActivity::class.java).putExtra(
|
||||
"mediaId", media.id
|
||||
),
|
||||
Intent(context, MediaDetailsActivity::class.java).putExtra("mediaId", media.id),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
@ -41,14 +35,11 @@ class SubscriptionItem(
|
|||
binding.deleteSubscription.setOnClickListener {
|
||||
SubscriptionHelper.deleteSubscription(id, true)
|
||||
adapter.remove(this)
|
||||
onItemRemoved(id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayout(): Int {
|
||||
return R.layout.item_subscription
|
||||
}
|
||||
override fun getLayout(): Int = R.layout.item_subscription
|
||||
|
||||
override fun initializeViewBinding(p0: View): ItemSubscriptionBinding {
|
||||
return ItemSubscriptionBinding.bind(p0)
|
||||
}
|
||||
override fun initializeViewBinding(view: View): ItemSubscriptionBinding = ItemSubscriptionBinding.bind(view)
|
||||
}
|
113
app/src/main/java/ani/dantotsu/settings/SubscriptionSource.kt
Normal file
113
app/src/main/java/ani/dantotsu/settings/SubscriptionSource.kt
Normal file
|
@ -0,0 +1,113 @@
|
|||
package ani.dantotsu.settings
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.ItemExtensionBinding
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
|
||||
class SubscriptionSource(
|
||||
private val parserName: String,
|
||||
private val subscriptions: MutableList<SubscriptionHelper.Companion.SubscribeMedia>,
|
||||
private val adapter: GroupieAdapter,
|
||||
private var parserIcon: Drawable? = null,
|
||||
private val onGroupRemoved: (SubscriptionSource) -> Unit
|
||||
) : BindableItem<ItemExtensionBinding>() {
|
||||
private lateinit var binding: ItemExtensionBinding
|
||||
private var isExpanded = false
|
||||
|
||||
override fun bind(viewBinding: ItemExtensionBinding, position: Int) {
|
||||
binding = viewBinding
|
||||
binding.extensionNameTextView.text = parserName
|
||||
updateSubscriptionCount()
|
||||
binding.extensionSubscriptions.visibility = View.VISIBLE
|
||||
|
||||
binding.extensionSubscriptions.setOnClickListener(null)
|
||||
binding.root.setOnClickListener {
|
||||
isExpanded = !isExpanded
|
||||
toggleSubscriptions()
|
||||
}
|
||||
binding.subscriptionCount.setOnClickListener {
|
||||
showRemoveAllSubscriptionsDialog(it.context)
|
||||
}
|
||||
binding.extensionIconImageView.visibility = View.VISIBLE
|
||||
val layoutParams = binding.extensionIconImageView.layoutParams as ViewGroup.MarginLayoutParams
|
||||
layoutParams.leftMargin = 28
|
||||
binding.extensionIconImageView.layoutParams = layoutParams
|
||||
|
||||
parserIcon?.let {
|
||||
binding.extensionIconImageView.setImageDrawable(it)
|
||||
} ?: run {
|
||||
binding.extensionIconImageView.setImageResource(R.drawable.control_background_40dp)
|
||||
}
|
||||
|
||||
binding.extensionPinImageView.visibility = View.GONE
|
||||
binding.extensionVersionTextView.visibility = View.GONE
|
||||
binding.closeTextView.visibility = View.GONE
|
||||
binding.settingsImageView.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun updateSubscriptionCount() {
|
||||
binding.subscriptionCount.text = subscriptions.size.toString()
|
||||
binding.subscriptionCount.visibility = if (subscriptions.isEmpty()) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
private fun showRemoveAllSubscriptionsDialog(context: Context) {
|
||||
AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.remove_all_subscriptions)
|
||||
.setMessage(context.getString(R.string.remove_all_subscriptions_desc, parserName))
|
||||
.setPositiveButton(R.string.apply) { _, _ ->
|
||||
removeAllSubscriptions()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun removeAllSubscriptions() {
|
||||
subscriptions.forEach { subscription ->
|
||||
SubscriptionHelper.deleteSubscription(subscription.id, false)
|
||||
}
|
||||
if (isExpanded) {
|
||||
val startPosition = adapter.getAdapterPosition(this) + 1
|
||||
repeat(subscriptions.size) {
|
||||
adapter.removeGroupAtAdapterPosition(startPosition)
|
||||
}
|
||||
}
|
||||
subscriptions.clear()
|
||||
onGroupRemoved(this)
|
||||
}
|
||||
|
||||
private fun removeSubscription(id: Any?) {
|
||||
subscriptions.removeAll { it.id == id }
|
||||
updateSubscriptionCount()
|
||||
if (subscriptions.isEmpty()) {
|
||||
onGroupRemoved(this)
|
||||
} else {
|
||||
adapter.notifyItemChanged(adapter.getAdapterPosition(this))
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleSubscriptions() {
|
||||
val startPosition = adapter.getAdapterPosition(this) + 1
|
||||
if (isExpanded) {
|
||||
subscriptions.forEachIndexed { index, subscribeMedia ->
|
||||
adapter.add(startPosition + index, SubscriptionItem(subscribeMedia.id, subscribeMedia, adapter) { removedId ->
|
||||
removeSubscription(removedId)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
repeat(subscriptions.size) {
|
||||
adapter.removeGroupAtAdapterPosition(startPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayout(): Int = R.layout.item_extension
|
||||
|
||||
override fun initializeViewBinding(view: View): ItemExtensionBinding = ItemExtensionBinding.bind(view)
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package ani.dantotsu.settings
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -9,13 +10,21 @@ import ani.dantotsu.BottomSheetDialogFragment
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.BottomSheetRecyclerBinding
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
import ani.dantotsu.parsers.novel.NovelExtensionManager
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
|
||||
private var _binding: BottomSheetRecyclerBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val adapter: GroupieAdapter = GroupieAdapter()
|
||||
private var subscriptions: Map<Int, SubscriptionHelper.Companion.SubscribeMedia> = mapOf()
|
||||
private val animeExtension: AnimeExtensionManager = Injekt.get()
|
||||
private val mangaExtensions: MangaExtensionManager = Injekt.get()
|
||||
private val novelExtensions: NovelExtensionManager = Injekt.get()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
@ -36,8 +45,33 @@ class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
|
|||
val context = requireContext()
|
||||
binding.title.text = context.getString(R.string.subscriptions)
|
||||
binding.replyButton.visibility = View.GONE
|
||||
subscriptions.forEach { (id, media) ->
|
||||
adapter.add(SubscriptionItem(id, media, adapter))
|
||||
|
||||
val groupedSubscriptions = subscriptions.values.groupBy {
|
||||
if (it.isAnime) SubscriptionHelper.getAnimeParser(it.id).name
|
||||
else SubscriptionHelper.getMangaParser(it.id).name
|
||||
}
|
||||
|
||||
groupedSubscriptions.forEach { (parserName, mediaList) ->
|
||||
adapter.add(SubscriptionSource(
|
||||
parserName,
|
||||
mediaList.toMutableList(),
|
||||
adapter,
|
||||
getParserIcon(parserName)
|
||||
) { group ->
|
||||
adapter.remove(group)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun getParserIcon(parserName: String): Drawable? {
|
||||
return when {
|
||||
animeExtension.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||
animeExtension.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||
mangaExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||
mangaExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||
novelExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||
novelExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
|
||||
class UserInterfaceSettingsActivity : AppCompatActivity() {
|
||||
lateinit var binding: ActivityUserInterfaceSettingsBinding
|
||||
|
@ -38,20 +39,23 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
|
|||
binding.uiSettingsHomeLayout.setOnClickListener {
|
||||
val set = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout).toMutableList()
|
||||
val views = resources.getStringArray(R.array.home_layouts)
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.home_layout_show)).apply {
|
||||
setMultiChoiceItems(
|
||||
views,
|
||||
PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout).toBooleanArray()
|
||||
) { _, i, value ->
|
||||
set[i] = value
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.home_layout_show))
|
||||
multiChoiceItems(
|
||||
items = views,
|
||||
checkedItems = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout).toBooleanArray()
|
||||
) { selectedItems ->
|
||||
for (i in selectedItems.indices) {
|
||||
set[i] = selectedItems[i]
|
||||
}
|
||||
setPositiveButton("Done") { _, _ ->
|
||||
PrefManager.setVal(PrefName.HomeLayout, set)
|
||||
restartApp()
|
||||
}
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
setPosButton(R.string.ok) {
|
||||
PrefManager.setVal(PrefName.HomeLayout, set)
|
||||
restartApp()
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
binding.uiSettingsSmallView.isChecked = PrefManager.getVal(PrefName.SmallView)
|
||||
|
|
|
@ -22,6 +22,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
|
|||
CheckUpdate(Pref(Location.General, Boolean::class, true)),
|
||||
VerboseLogging(Pref(Location.General, Boolean::class, false)),
|
||||
DohProvider(Pref(Location.General, Int::class, 0)),
|
||||
HidePrivate(Pref(Location.General, Boolean::class, false)),
|
||||
DefaultUserAgent(
|
||||
Pref(
|
||||
Location.General,
|
||||
|
|
|
@ -26,7 +26,7 @@ import io.noties.markwon.editor.MarkwonEditorTextWatcher
|
|||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
|
||||
class MarkdownCreatorActivity : AppCompatActivity() {
|
||||
class ActivityMarkdownCreator : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMarkdownCreatorBinding
|
||||
private lateinit var type: String
|
||||
private var text: String = ""
|
||||
|
@ -80,24 +80,28 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
finish()
|
||||
return
|
||||
}
|
||||
binding.markdownCreatorTitle.text = when (type) {
|
||||
"activity" -> getString(R.string.create_new_activity)
|
||||
"review" -> getString(R.string.create_new_review)
|
||||
"message" -> getString(R.string.create_new_message)
|
||||
"replyActivity" -> {
|
||||
parentId = intent.getIntExtra("parentId", -1)
|
||||
if (parentId == -1) {
|
||||
toast("Error: No parent ID")
|
||||
finish()
|
||||
return
|
||||
}
|
||||
getString(R.string.create_new_reply)
|
||||
val editId = intent.getIntExtra("edit", -1)
|
||||
val userId = intent.getIntExtra("userId", -1)
|
||||
parentId = intent.getIntExtra("parentId", -1)
|
||||
when (type) {
|
||||
"replyActivity" -> if (parentId == -1) {
|
||||
toast("Error: No parent ID")
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
else -> ""
|
||||
"message" -> {
|
||||
if (editId == -1) {
|
||||
binding.privateCheckbox.visibility = ViewGroup.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
var private = false
|
||||
binding.privateCheckbox.setOnCheckedChangeListener { _, isChecked ->
|
||||
private = isChecked
|
||||
}
|
||||
|
||||
ping = intent.getStringExtra("other")
|
||||
val userId = intent.getIntExtra("userId", -1)
|
||||
text = ping ?: ""
|
||||
binding.editText.setText(text)
|
||||
binding.editText.addTextChangedListener {
|
||||
|
@ -116,12 +120,11 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
toast(getString(R.string.cannot_be_empty))
|
||||
return@setOnClickListener
|
||||
}
|
||||
AlertDialog.Builder(this, R.style.MyPopup).apply {
|
||||
customAlertDialog().apply {
|
||||
setTitle(R.string.warning)
|
||||
setMessage(R.string.post_to_anilist_warning)
|
||||
setPositiveButton(R.string.ok) { _, _ ->
|
||||
setPosButton(R.string.ok) {
|
||||
launchIO {
|
||||
val editId = intent.getIntExtra("edit", -1)
|
||||
val isEdit = editId != -1
|
||||
val success = when (type) {
|
||||
"activity" -> if (isEdit) {
|
||||
|
@ -135,25 +138,27 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
} else {
|
||||
Anilist.mutation.postReply(parentId, text)
|
||||
}
|
||||
"message" -> if (isEdit) { //TODO private
|
||||
Anilist.mutation.postMessage(userId , text, editId)
|
||||
"message" -> if (isEdit) {
|
||||
Anilist.mutation.postMessage(userId, text, editId)
|
||||
} else {
|
||||
Anilist.mutation.postMessage(userId , text)
|
||||
Anilist.mutation.postMessage(userId, text, isPrivate = private)
|
||||
}
|
||||
|
||||
else -> "Error: Unknown type"
|
||||
}
|
||||
toast(success)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
setNeutralButton(R.string.open_rules) { _, _ ->
|
||||
setNeutralButton(R.string.open_rules) {
|
||||
openLinkInBrowser("https://anilist.co/forum/thread/14")
|
||||
}
|
||||
setNegativeButton(R.string.cancel, null)
|
||||
}.show()
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
binding.createButton.setOnLongClickListener {
|
||||
binding.previewCheckbox.setOnClickListener {
|
||||
isPreviewMode = !isPreviewMode
|
||||
previewMarkdown(isPreviewMode)
|
||||
if (isPreviewMode) {
|
||||
|
@ -161,7 +166,6 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
} else {
|
||||
toast("Preview disabled")
|
||||
}
|
||||
true
|
||||
}
|
||||
binding.editText.requestFocus()
|
||||
setupMarkdownButtons()
|
||||
|
@ -187,9 +191,11 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
MarkdownFormat.UNORDERED_LIST -> {
|
||||
lines.joinToString("\n") { "- $it" }
|
||||
}
|
||||
|
||||
MarkdownFormat.ORDERED_LIST -> {
|
||||
lines.mapIndexed { index, line -> "${index + 1}. $line" }.joinToString("\n")
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (format.syntax.contains("%s")) {
|
||||
String.format(format.syntax, selectedText)
|
||||
|
@ -222,7 +228,6 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
boxBackgroundMode = TextInputLayout.BOX_BACKGROUND_OUTLINE
|
||||
hint = "Paste your link here"
|
||||
isHintEnabled = true
|
||||
}
|
||||
|
||||
|
@ -241,30 +246,20 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
setPadding(64, 64, 64, 0)
|
||||
setPadding(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup).apply {
|
||||
setView(container)
|
||||
setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
customAlertDialog().apply {
|
||||
setTitle("Paste your link here")
|
||||
setCustomView(container)
|
||||
setPosButton(getString(R.string.ok)) {
|
||||
val input = inputEditText.text.toString()
|
||||
val formattedText = String.format(format.syntax, input)
|
||||
binding.editText.text?.insert(position, formattedText)
|
||||
binding.editText.setSelection(position + formattedText.length)
|
||||
dialog.dismiss()
|
||||
}
|
||||
setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
}.create()
|
||||
setNegButton(getString(R.string.cancel))
|
||||
}.show()
|
||||
|
||||
val widthInDp = 245
|
||||
val layoutParams = ViewGroup.LayoutParams(
|
||||
(widthInDp * resources.displayMetrics.density).toInt(),
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
dialog.window?.setLayout(layoutParams.width, layoutParams.height)
|
||||
dialog.show()
|
||||
inputEditText.requestFocus()
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package ani.dantotsu.util
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
|
@ -20,7 +21,24 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
private var selectedItemIndex: Int = -1
|
||||
private var onItemSelected: ((Int) -> Unit)? = null
|
||||
private var customView: View? = null
|
||||
private var onShow: (() -> Unit)? = null
|
||||
private var attach: ((dialog: AlertDialog) -> Unit)? = null
|
||||
private var onDismiss: (() -> Unit)? = null
|
||||
private var onCancel: (() -> Unit)? = null
|
||||
private var cancelable: Boolean = true
|
||||
fun setCancelable(cancelable: Boolean): AlertDialogBuilder {
|
||||
this.cancelable = cancelable
|
||||
return this
|
||||
}
|
||||
fun setOnShowListener(onShow: () -> Unit): AlertDialogBuilder {
|
||||
this.onShow = onShow
|
||||
return this
|
||||
}
|
||||
fun setOnCancelListener(onCancel: () -> Unit): AlertDialogBuilder {
|
||||
this.onCancel = onCancel
|
||||
return this
|
||||
}
|
||||
|
||||
fun setTitle(title: String?): AlertDialogBuilder {
|
||||
this.title = title
|
||||
return this
|
||||
|
@ -45,6 +63,10 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
this.customView = view
|
||||
return this
|
||||
}
|
||||
fun setCustomView(layoutResId: Int): AlertDialogBuilder {
|
||||
this.customView = View.inflate(context, layoutResId, null)
|
||||
return this
|
||||
}
|
||||
|
||||
fun setPosButton(title: String?, onClick: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.posButtonTitle = title
|
||||
|
@ -52,11 +74,7 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
return this
|
||||
}
|
||||
|
||||
fun setPosButton(
|
||||
int: Int,
|
||||
formatArgs: Int? = null,
|
||||
onClick: (() -> Unit)? = null
|
||||
): AlertDialogBuilder {
|
||||
fun setPosButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.posButtonTitle = context.getString(int, formatArgs)
|
||||
this.onPositiveButtonClick = onClick
|
||||
return this
|
||||
|
@ -68,11 +86,7 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
return this
|
||||
}
|
||||
|
||||
fun setNegButton(
|
||||
int: Int,
|
||||
formatArgs: Int? = null,
|
||||
onClick: (() -> Unit)? = null
|
||||
): AlertDialogBuilder {
|
||||
fun setNegButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.negButtonTitle = context.getString(int, formatArgs)
|
||||
this.onNegativeButtonClick = onClick
|
||||
return this
|
||||
|
@ -84,11 +98,7 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
return this
|
||||
}
|
||||
|
||||
fun setNeutralButton(
|
||||
int: Int,
|
||||
formatArgs: Int? = null,
|
||||
onClick: (() -> Unit)? = null
|
||||
): AlertDialogBuilder {
|
||||
fun setNeutralButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.neutralButtonTitle = context.getString(int, formatArgs)
|
||||
this.onNeutralButtonClick = onClick
|
||||
return this
|
||||
|
@ -99,22 +109,19 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
return this
|
||||
}
|
||||
|
||||
fun singleChoiceItems(
|
||||
items: Array<String>,
|
||||
selectedItemIndex: Int = -1,
|
||||
onItemSelected: (Int) -> Unit
|
||||
): AlertDialogBuilder {
|
||||
fun onDismiss(onDismiss: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.onDismiss = onDismiss
|
||||
return this
|
||||
}
|
||||
|
||||
fun singleChoiceItems(items: Array<String>, selectedItemIndex: Int = -1, onItemSelected: (Int) -> Unit): AlertDialogBuilder {
|
||||
this.items = items
|
||||
this.selectedItemIndex = selectedItemIndex
|
||||
this.onItemSelected = onItemSelected
|
||||
return this
|
||||
}
|
||||
|
||||
fun multiChoiceItems(
|
||||
items: Array<String>,
|
||||
checkedItems: BooleanArray? = null,
|
||||
onItemsSelected: (BooleanArray) -> Unit
|
||||
): AlertDialogBuilder {
|
||||
fun multiChoiceItems(items: Array<String>, checkedItems: BooleanArray? = null, onItemsSelected: (BooleanArray) -> Unit): AlertDialogBuilder {
|
||||
this.items = items
|
||||
this.checkedItems = checkedItems ?: BooleanArray(items.size) { false }
|
||||
this.onItemsSelected = onItemsSelected
|
||||
|
@ -122,15 +129,18 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
}
|
||||
|
||||
fun show() {
|
||||
if (context is Activity && context.isFinishing) return // Ensure context is valid
|
||||
|
||||
val builder = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
if (title != null) builder.setTitle(title)
|
||||
if (message != null) builder.setMessage(message)
|
||||
if (customView != null) builder.setView(customView)
|
||||
if (items != null) {
|
||||
if (onItemSelected != null) {
|
||||
builder.setSingleChoiceItems(items, selectedItemIndex) { _, which ->
|
||||
builder.setSingleChoiceItems(items, selectedItemIndex) { dialog, which ->
|
||||
selectedItemIndex = which
|
||||
onItemSelected?.invoke(which)
|
||||
dialog.dismiss()
|
||||
}
|
||||
} else if (checkedItems != null && onItemsSelected != null) {
|
||||
builder.setMultiChoiceItems(items, checkedItems) { _, which, isChecked ->
|
||||
|
@ -157,13 +167,23 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
builder.setCancelable(false)
|
||||
if (onCancel != null) {
|
||||
builder.setOnCancelListener {
|
||||
onCancel?.invoke()
|
||||
}
|
||||
}
|
||||
builder.setCancelable(cancelable)
|
||||
val dialog = builder.create()
|
||||
attach?.invoke(dialog)
|
||||
dialog.setOnDismissListener {
|
||||
onDismiss?.invoke()
|
||||
}
|
||||
dialog.setOnShowListener {
|
||||
onShow?.invoke()
|
||||
}
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun Context.customAlertDialog(): AlertDialogBuilder {
|
||||
|
|
|
@ -71,20 +71,17 @@ class StoragePermissions {
|
|||
complete(true)
|
||||
return
|
||||
}
|
||||
val builder = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
builder.setTitle(getString(R.string.dir_access))
|
||||
builder.setMessage(getString(R.string.dir_access_msg))
|
||||
builder.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
launcher.registerForCallback(complete)
|
||||
launcher.launch()
|
||||
dialog.dismiss()
|
||||
}
|
||||
builder.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
complete(false)
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.dir_access))
|
||||
setMessage(getString(R.string.dir_access_msg))
|
||||
setPosButton(getString(R.string.ok)) {
|
||||
launcher.registerForCallback(complete)
|
||||
launcher.launch()
|
||||
}
|
||||
setNegButton(getString(R.string.cancel)) {
|
||||
complete(false)
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
|
||||
private fun pathToUri(path: String): Uri {
|
||||
|
|
|
@ -64,10 +64,6 @@ internal class ExtensionGithubApi {
|
|||
|
||||
val repos =
|
||||
PrefManager.getVal<Set<String>>(PrefName.AnimeExtensionRepos).toMutableList()
|
||||
if (repos.isEmpty()) {
|
||||
repos.add("https://raw.githubusercontent.com/aniyomiorg/aniyomi-extensions/repo")
|
||||
PrefManager.setVal(PrefName.AnimeExtensionRepos, repos.toSet())
|
||||
}
|
||||
|
||||
repos.forEach {
|
||||
try {
|
||||
|
@ -95,9 +91,10 @@ internal class ExtensionGithubApi {
|
|||
|
||||
// Sanity check - a small number of extensions probably means something broke
|
||||
// with the repo generator
|
||||
if (repoExtensions.size < 10) {
|
||||
throw Exception()
|
||||
}
|
||||
//if (repoExtensions.size < 10) {
|
||||
// throw Exception()
|
||||
//}
|
||||
// No official repo now so this won't be needed anymore. User-made repo can have less than 10 extensions
|
||||
|
||||
extensions.addAll(repoExtensions)
|
||||
} catch (e: Throwable) {
|
||||
|
@ -157,10 +154,6 @@ internal class ExtensionGithubApi {
|
|||
|
||||
val repos =
|
||||
PrefManager.getVal<Set<String>>(PrefName.MangaExtensionRepos).toMutableList()
|
||||
if (repos.isEmpty()) {
|
||||
repos.add("https://raw.githubusercontent.com/keiyoushi/extensions/main")
|
||||
PrefManager.setVal(PrefName.MangaExtensionRepos, repos.toSet())
|
||||
}
|
||||
|
||||
repos.forEach {
|
||||
try {
|
||||
|
@ -188,9 +181,10 @@ internal class ExtensionGithubApi {
|
|||
|
||||
// Sanity check - a small number of extensions probably means something broke
|
||||
// with the repo generator
|
||||
if (repoExtensions.size < 10) {
|
||||
throw Exception()
|
||||
}
|
||||
//if (repoExtensions.size < 10) {
|
||||
// throw Exception()
|
||||
//}
|
||||
// No official repo now so this won't be needed anymore. User made repo can have less than 10 extensions.
|
||||
|
||||
extensions.addAll(repoExtensions)
|
||||
} catch (e: Throwable) {
|
||||
|
|
10
app/src/main/res/drawable/ic_round_history_24.xml
Normal file
10
app/src/main/res/drawable/ic_round_history_24.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M13.26,3C8.17,2.86 4,6.95 4,12L2.21,12c-0.45,0 -0.67,0.54 -0.35,0.85l2.79,2.8c0.2,0.2 0.51,0.2 0.71,0l2.79,-2.8c0.31,-0.31 0.09,-0.85 -0.36,-0.85L6,12c0,-3.9 3.18,-7.05 7.1,-7 3.72,0.05 6.85,3.18 6.9,6.9 0.05,3.91 -3.1,7.1 -7,7.1 -1.61,0 -3.1,-0.55 -4.28,-1.48 -0.4,-0.31 -0.96,-0.28 -1.32,0.08 -0.42,0.42 -0.39,1.13 0.08,1.49C9,20.29 10.91,21 13,21c5.05,0 9.14,-4.17 9,-9.26 -0.13,-4.69 -4.05,-8.61 -8.74,-8.74zM12.75,8c-0.41,0 -0.75,0.34 -0.75,0.75v3.68c0,0.35 0.19,0.68 0.49,0.86l3.12,1.85c0.36,0.21 0.82,0.09 1.03,-0.26 0.21,-0.36 0.09,-0.82 -0.26,-1.03l-2.88,-1.71v-3.4c0,-0.4 -0.34,-0.74 -0.75,-0.74z"/>
|
||||
</vector>
|
11
app/src/main/res/drawable/ic_round_library_books_24.xml
Normal file
11
app/src/main/res/drawable/ic_round_library_books_24.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,6c-0.55,0 -1,0.45 -1,1v13c0,1.1 0.9,2 2,2h13c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1L5,20c-0.55,0 -1,-0.45 -1,-1L4,7c0,-0.55 -0.45,-1 -1,-1zM20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,11h-8c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1zM14,15h-4c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h4c0.55,0 1,0.45 1,1s-0.45,1 -1,1zM18,7h-8c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"/>
|
||||
|
||||
</vector>
|
|
@ -55,6 +55,15 @@
|
|||
app:srcCompat="@drawable/ic_round_search_24"
|
||||
app:tint="?attr/colorOnBackground" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/listed"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/listed_in_library"
|
||||
app:srcCompat="@drawable/ic_round_library_books_24"
|
||||
app:tint="?attr/colorOnBackground" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/random"
|
||||
android:layout_width="40dp"
|
||||
|
|
|
@ -1,93 +1,100 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout 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="match_parent"
|
||||
android:fitsSystemWindows="false">
|
||||
android:fitsSystemWindows="false"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/markdownCreatorToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
android:layout_height="48dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/markdownCreatorToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
<ImageView
|
||||
android:id="@+id/markdownCreatorBack"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:layout_marginStart="12dp"
|
||||
android:src="@drawable/ic_round_arrow_back_ios_new_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/markdownCreatorBack"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:layout_marginStart="12dp"
|
||||
android:src="@drawable/ic_round_arrow_back_ios_new_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/markdownCreatorTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="44dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:gravity="center|start"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
android:textSize="18sp"
|
||||
tools:text="@string/placeholder" />
|
||||
<CheckBox
|
||||
android:id="@+id/privateCheckbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/preview"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/private_mode"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/createButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:maxLines="1"
|
||||
android:text="@string/publish"
|
||||
app:cornerRadius="16dp"
|
||||
tools:ignore="ButtonStyle" />
|
||||
</FrameLayout>
|
||||
<CheckBox
|
||||
android:id="@+id/previewCheckbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:contentDescription="@string/preview"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/preview"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="590dp"
|
||||
android:fontFamily="@font/poppins"
|
||||
android:inputType="textMultiLine"
|
||||
android:padding="16dp"
|
||||
android:nestedScrollingEnabled="true"
|
||||
android:gravity="top|start"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp"
|
||||
android:hint="@string/reply_hint"
|
||||
tools:ignore="LabelFor" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
<ImageButton
|
||||
android:id="@+id/createButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/ic_round_send_24"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:gravity="top|start"
|
||||
android:hint="@string/reply_hint"
|
||||
android:inputType="textMultiLine"
|
||||
android:nestedScrollingEnabled="true"
|
||||
android:padding="16dp"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="18sp"
|
||||
tools:ignore="LabelFor" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/markdownOptionsContainer"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -99,155 +106,170 @@
|
|||
android:windowSoftInputMode="adjustResize">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatBold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_bold_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatItalic"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_italic_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatStrikethrough"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_strikethrough_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatSpoiler"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_spoiler_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatLink"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_link_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatImage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_image_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatYoutube"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_youtube_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatVideo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_video_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatListOrdered"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_list_numbered_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatListUnordered"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_list_bulleted_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_title_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatCenter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_align_center_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatQuote"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_quote_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatCode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/format_code_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/formatVideo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/format_video_24"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</LinearLayout>
|
|
@ -42,6 +42,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="67dp"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
|
@ -50,15 +51,15 @@
|
|||
android:layout_height="match_parent"
|
||||
android:nestedScrollingEnabled="true"
|
||||
tools:ignore="SpeakableTextPresentCheck" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<nl.joery.animatedbottombar.AnimatedBottomBar
|
||||
android:id="@+id/notificationNavBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:layout_marginTop="-64dp"
|
||||
android:layout_marginTop="-67dp"
|
||||
android:background="?attr/colorSurface"
|
||||
android:padding="0dp"
|
||||
app:abb_animationInterpolator="@anim/over_shoot"
|
||||
|
@ -73,4 +74,5 @@
|
|||
app:itemTextAppearanceActive="@style/NavBarText"
|
||||
app:itemTextAppearanceInactive="@style/NavBarText"
|
||||
app:itemTextColor="@color/tab_layout_icon" />
|
||||
|
||||
</LinearLayout>
|
|
@ -54,7 +54,7 @@
|
|||
app:cardElevation="0dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/animeSourceList"
|
||||
android:id="@+id/mediaSourceList"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:alpha="0.33"
|
||||
|
@ -73,7 +73,7 @@
|
|||
app:cardElevation="0dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/animeSourceGrid"
|
||||
android:id="@+id/mediaSourceGrid"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:alpha="0.33"
|
||||
|
@ -91,7 +91,7 @@
|
|||
app:cardElevation="0dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/animeSourceCompact"
|
||||
android:id="@+id/mediaSourceCompact"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:alpha="0.33"
|
||||
|
@ -140,7 +140,7 @@
|
|||
app:cardElevation="0dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/animeSourceTop"
|
||||
android:id="@+id/mediaSourceTop"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
|
@ -189,7 +189,7 @@
|
|||
app:cardElevation="0dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/animeDownloadTop"
|
||||
android:id="@+id/mediaDownloadTop"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
|
@ -200,7 +200,7 @@
|
|||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/animeScanlatorContainer"
|
||||
android:id="@+id/mangaScanlatorContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical">
|
||||
|
@ -235,7 +235,7 @@
|
|||
app:cardElevation="0dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/animeScanlatorTop"
|
||||
android:id="@+id/mangaScanlatorTop"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
|
@ -246,7 +246,7 @@
|
|||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/animeWebviewContainer"
|
||||
android:id="@+id/mediaWebviewContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
|
@ -280,7 +280,7 @@
|
|||
android:layout_height="48dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/animeWebViewTop"
|
||||
android:id="@+id/mediaWebViewTop"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center|center_horizontal"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
tools:context=".media.anime.AnimeWatchFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/animeNotSupported"
|
||||
android:id="@+id/mediaNotSupported"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
|
@ -31,7 +31,7 @@
|
|||
tools:visibility="gone" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/animeSourceRecycler"
|
||||
android:id="@+id/mediaSourceRecycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
|
@ -39,7 +39,7 @@
|
|||
android:paddingEnd="24dp"
|
||||
android:paddingBottom="128dp"
|
||||
tools:itemCount="1"
|
||||
tools:listitem="@layout/item_anime_watch" />
|
||||
tools:listitem="@layout/item_media_source" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/ScrollTop"
|
|
@ -65,19 +65,6 @@
|
|||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/addStory"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleX="2.2"
|
||||
android:scaleY="2.2"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_circle_add"
|
||||
app:layout_goneMarginBottom="40dp"
|
||||
app:layout_goneMarginRight="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/textActivityContainer"
|
||||
app:layout_constraintEnd_toEndOf="@id/textActivityContainer" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -215,7 +202,7 @@
|
|||
android:id="@+id/activityRepliesContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:padding="12dp"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
|
@ -243,7 +230,7 @@
|
|||
android:id="@+id/activityLikeContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:padding="12dp"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
|
|
|
@ -129,7 +129,6 @@
|
|||
android:textSize="12sp"
|
||||
tools:visibility="visible"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/activityDelete"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -14,21 +14,21 @@
|
|||
android:background="?attr/colorSurfaceVariant" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/itemEpisodeProgressCont"
|
||||
android:id="@+id/itemMediaProgressCont"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<View
|
||||
android:id="@+id/itemEpisodeProgress"
|
||||
android:id="@+id/itemMediaProgress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_weight="0"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
<View
|
||||
android:id="@+id/itemEpisodeProgressEmpty"
|
||||
android:id="@+id/itemMediaProgressEmpty"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_weight="1" />
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
app:cardElevation="4dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemEpisodeImage"
|
||||
android:id="@+id/itemMediaImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="96dp"
|
||||
android:scaleType="centerCrop"
|
||||
|
@ -85,21 +85,21 @@
|
|||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/itemEpisodeProgressCont"
|
||||
android:id="@+id/itemMediaProgressCont"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<View
|
||||
android:id="@+id/itemEpisodeProgress"
|
||||
android:id="@+id/itemMediaProgress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_weight="0"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
<View
|
||||
android:id="@+id/itemEpisodeProgressEmpty"
|
||||
android:id="@+id/itemMediaProgressEmpty"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_weight="1" />
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
android:indeterminate="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemEpisodeImage"
|
||||
android:id="@+id/itemMediaImage"
|
||||
android:layout_width="164dp"
|
||||
android:layout_height="109dp"
|
||||
android:layout_gravity="center"
|
||||
|
@ -77,7 +77,7 @@
|
|||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/itemEpisodeProgressCont"
|
||||
android:id="@+id/itemMediaProgress_cont"
|
||||
android:layout_width="164dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
|
@ -85,14 +85,14 @@
|
|||
android:visibility="gone">
|
||||
|
||||
<View
|
||||
android:id="@+id/itemEpisodeProgress"
|
||||
android:id="@+id/itemMediaProgress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_weight="0"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
<View
|
||||
android:id="@+id/itemEpisodeProgressEmpty"
|
||||
android:id="@+id/itemMediaProgressEmpty"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_weight="1"
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="3dp"
|
||||
android:layout_marginEnd="9dp"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<LinearLayout
|
||||
|
@ -53,6 +53,26 @@
|
|||
tools:ignore="SmallSp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subscriptionCount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:padding="12dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/extensionSubscriptions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="0"
|
||||
android:src="@drawable/ui_bg"
|
||||
android:visibility="gone"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/closeTextView"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/animeSourceTitle"
|
||||
android:id="@+id/mediaSourceTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
|
@ -57,7 +57,7 @@
|
|||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/animeSourceNameContainer"
|
||||
android:id="@+id/mediaSourceNameContainer"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
|
@ -72,7 +72,7 @@
|
|||
app:startIconDrawable="@drawable/ic_round_source_24">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/animeSource"
|
||||
android:id="@+id/mediaSource"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
|
@ -91,7 +91,7 @@
|
|||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/animeSourceSettings"
|
||||
android:id="@+id/mediaSourceSettings"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
|
@ -107,7 +107,7 @@
|
|||
android:baselineAligned="false">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/animeSourceLanguageContainer"
|
||||
android:id="@+id/mediaSourceLanguageContainer"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
|
@ -123,7 +123,7 @@
|
|||
app:startIconDrawable="@drawable/ic_round_source_24">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/animeSourceLanguage"
|
||||
android:id="@+id/mediaSourceLanguage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
|
@ -193,7 +193,7 @@
|
|||
|
||||
<TextView
|
||||
|
||||
android:id="@+id/animeSourceSearch"
|
||||
android:id="@+id/mediaSourceSearch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
|
@ -224,7 +224,7 @@
|
|||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/animeSourceSubscribe"
|
||||
android:id="@+id/mediaSourceSubscribe"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
|
@ -235,7 +235,7 @@
|
|||
tools:ignore="ContentDescription,ImageContrastCheck" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/animeNestedButton"
|
||||
android:id="@+id/mediaNestedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
|
@ -247,7 +247,7 @@
|
|||
</LinearLayout>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/animeSourceContinue"
|
||||
android:id="@+id/sourceContinue"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_gravity="center"
|
||||
|
@ -259,7 +259,7 @@
|
|||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemEpisodeImage"
|
||||
android:id="@+id/itemMediaImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
|
@ -280,7 +280,7 @@
|
|||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/animeSourceContinueText"
|
||||
android:id="@+id/mediaSourceContinueText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
|
@ -293,21 +293,21 @@
|
|||
app:drawableEndCompat="@drawable/ic_round_play_arrow_24" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/itemEpisodeProgressCont"
|
||||
android:id="@+id/itemMediaProgressCont"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<View
|
||||
android:id="@+id/itemEpisodeProgress"
|
||||
android:id="@+id/itemMediaProgress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_weight="0"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
<View
|
||||
android:id="@+id/itemEpisodeProgressEmpty"
|
||||
android:id="@+id/itemMediaProgressEmpty"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_weight="1" />
|
||||
|
@ -318,7 +318,7 @@
|
|||
</LinearLayout>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/animeWatchChipScroll"
|
||||
android:id="@+id/mediaWatchChipScroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
|
@ -328,7 +328,7 @@
|
|||
android:scrollbars="none">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/animeSourceChipGroup"
|
||||
android:id="@+id/mediaSourceChipGroup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleLine="true"
|
||||
|
@ -336,7 +336,7 @@
|
|||
</HorizontalScrollView>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/animeSourceProgressBar"
|
||||
android:id="@+id/sourceProgressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -350,7 +350,7 @@
|
|||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/animeSourceNotFound"
|
||||
android:id="@+id/sourceNotFound"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
|
@ -364,6 +364,7 @@
|
|||
android:id="@+id/faqbutton"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginTop="-16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:backgroundTint="?attr/colorPrimaryContainer"
|
||||
android:fontFamily="@font/poppins_bold"
|
|
@ -25,7 +25,7 @@
|
|||
app:startIconDrawable="@drawable/ic_round_source_24">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/animeSource"
|
||||
android:id="@+id/mediaSource"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
android:indeterminate="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemEpisodeImage"
|
||||
android:id="@+id/itemMediaImage"
|
||||
android:layout_width="108dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
|
|
|
@ -117,6 +117,32 @@
|
|||
app:drawableTint="?attr/colorPrimary" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/clearHistory"
|
||||
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/clear_history"
|
||||
android:textColor="?attr/colorPrimary"
|
||||
app:drawableStartCompat="@drawable/ic_round_history_24"
|
||||
app:drawableTint="?attr/colorPrimary" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<ani.dantotsu.FadingEdgeRecyclerView
|
||||
android:id="@+id/searchChipRecycler"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
|
|
@ -156,8 +156,12 @@
|
|||
<string name="chap">Chapter</string>
|
||||
<string name="wrong"><u>Wrong Title?</u></string>
|
||||
<string name="source_not_found">
|
||||
Couldn\'t find anything X( \n
|
||||
Try another source.
|
||||
Nothing came up from this source.\n
|
||||
Let\'s look elsewhere.
|
||||
</string>
|
||||
<string name="download_not_found">
|
||||
Your downloads are feeling a bit lonely…\n
|
||||
Try downloading something.
|
||||
</string>
|
||||
<string name="not_supported">%1$s is not supported!</string>
|
||||
<string name="server_selector">Select Server</string>
|
||||
|
@ -413,6 +417,8 @@
|
|||
<string name="use_alarm_manager_reliable">Use Alarm Manager for reliable Notifications</string>
|
||||
<string name="use_alarm_manager_confirm">Using Alarm Manger can help fight against battery optimization, but may consume more battery. It also requires the Alarm Manager permission.</string>
|
||||
<string name="use">Use</string>
|
||||
<string name="remove_all_subscriptions">Remove All Subscriptions</string>
|
||||
<string name="remove_all_subscriptions_desc">Are you sure you want to remove all subscriptions for %1$s?</string>
|
||||
<string name="checking_subscriptions">Notification for Checking Subscriptions</string>
|
||||
<string name="subscriptions_checking_time_s">Subscriptions Update Frequency : %1$s</string>
|
||||
<string name="subscriptions_checking_time">Subscriptions Update Frequency</string>
|
||||
|
@ -629,13 +635,7 @@
|
|||
<string name="answer_6">This is because it updates every 48 hours automatically (by Anilist). If you really need to update your stats, you can force update your stats after going to this [link](https://anilist.co/settings/lists).</string>
|
||||
|
||||
<string name="question_7">How to download Anime?</string>
|
||||
<string name="answer_7">There are two methods of downloading currently. One is internal and the other is external. If you download internally, then it can be viewed within the app but only the app can open that episode, you cannot move it or share it. The other option is to use external downloading. It requires a download manager to download and a separate video player to watch. External downloads can be shared but you cannot view it within the Dantotsu app.\n\n•To download internally:\n\n1. Tap the download button.\n2. Pick the server and the video quality.\n3. Profit.\n\n•To download externally:\n\n 1. Download 1DM or ADM from Google Play Store.
|
||||
\n2. Enter the app, give storage access and set your preferences (downloading speed, downloading path etc(optional))
|
||||
\n3. Now go to \`Dantotsu > Settings > Common > Download Managers\` and choose the download manager you just set up.
|
||||
\n4. Go to your desired episode and press on the download icon of any server. There may be a popup to set your preferences again, just press on "Download" and it will be saved in the directed path.
|
||||
|
||||
\n\nNote: Direct downloads are also possible without a manager but it\'s not recommended.
|
||||
\n\nNerd Note: Internally downloaded episodes are stored in \`Android/data/ani.dantotsu.*/files/Anime_Downloads\`\nYou cannot play those files as they are in \`.exo\` format, split into hundreds of pieces and are encrypted.</string>
|
||||
<string name="answer_7">There are two methods of downloading. Internal and external. If you download internally, then it can be viewed within the app and tracking will work normally for it. The other option is to use external downloader. It requires a download manager to download and a separate video player to watch. External downloads cannot be viewed within the Dantotsu app.\n\n•To download internally:\n\n1. Tap the download button.\n2. For the first time, it will ask you to set a download location. All your downloads will be stored there.\n3. Pick the server and the video quality.\n4. Profit.\n\n•To download externally:\n\n 1. Download 1DM or ADM from Google Play Store.\n2. Enter the app, give storage access and set your preferences (downloading speed, downloading path etc(optional))\n3. Now go to \`Dantotsu > Settings > Common > Download Managers\` and choose the download manager you just set up.\n4. Go to your desired episode and press on the download icon of any server. There may be a popup to set your preferences again, just press on "Download" and it will be saved in the directed path.\n\nNote: External downloads are also possible without a manager but it\'s not recommended.\n\nNerd Note: Internally downloaded episodes are stored in \`{your set location}/Dantotsu/Anime/*`\nYou can change your download location in settings but your previous downloaded episodes will not show up in the app anymore.</string>
|
||||
|
||||
<string name="question_9">How to enable NSFW content?</string>
|
||||
<string name="answer_9">You can enable NSFW content by enabling 18+ contents from this [link](https://anilist.co/settings/media). You also have to enable NSFW extensions in \`Settings > Extensions > NSFW extensions\` </string>
|
||||
|
@ -664,6 +664,11 @@
|
|||
<string name="question_17">Some useful tips and tricks</string>
|
||||
<string name="answer_17">The following presents some tips and tricks you may or may not know about - \n \n \n - By hold pressing the Dantotsu logo in settings, you can check if there are any new updates manually. \n \n - Hold pressing an error message/tag/synonym or title will copy it. \n \n - You can open an episode with other apps by hold pressing any server for that episode. This helps in streaming the episode using other video players or download the episode using download managers. \n \n - You can set up custom lists using this [link](https://anilist.co/settings/lists). (you need to be signed in) \n \n - If your episode/chapter is not being progressed automatically after you finish watching/reading it, then hold press the status bar(planning/repeating/watching button) of that anime/manga. The next time you start a chapter/finish an episode, you will stumble upon a popup. Press yes there. </string>
|
||||
|
||||
<string name="question_18">I can\'t login to Anilist.</string>
|
||||
<string name="answer_18">The reason this happens is probably because you\'re not using the default browser.\n\n>You have to set Chrome as your default browser to login to Anilist.\n\n>It takes a few seconds for the login button to display changes.\n\nIf it doesn\'t work then you could possibly be IP banned from Anilist or your ISP banned Anilist themselves. We believe that this is highly unlikely so open [Anilist](https://anilist.co) in your browser to see if that\`s the case.</string>
|
||||
|
||||
<string name="question_19">What is torrent? How do I use it?</string>
|
||||
<string name="answer_19">Torrent or formally known as BitTorrent is an internet communication protocol for peer\-to\-peer file sharing. A torrent network doesn\'t use a centralised server to host files. It shares files in a decentralised manner. A torrent network has two types of peers. Seeders & Leachers.\n\n• Seeders : These are peers who completed downloading and has the full file. And now they are sharing this file to other peers which is called seeding. A torrent cannot work without at least one seeder. The more seeder a torrent has, the better.\n\n• Leachers : These are peers who are currently downloading the file. If they currently have 40% downloaded then they will share the 40% to any other peers who requests it.\n\nUnlike a centralised server, torrents have no bandwidth limit. You can get your files from hundreds of seeders at the highest possible speed your internet can offer. But many ISP throttle torrent to slow them down because it\'s demanding on their infrastructure. Use a VPN to circumvent this.\n\n• How to use torrents :\n\n1. Install the Torrent Add-on from \`Dantotsu > Settings > Add-ons > Torrent Add-on.\` \n2. Get a source that provides torrents.\n3. USE A VPN. Using VPN while torrenting only has upsides. Without a VPN your IP address will be exposed, your ISP will throttle your network and you could possibly be fined if you live in a country first world country. DO NOT USE IT WITHOUT A VPN IF YOU DON\'T KNOW WHAT YOU\'RE DOING.\n4. Now use that source to start torrenting.</string>
|
||||
|
||||
<string name="subscribed_notification">Subscribed! Receiving notifications, when new episodes are released on %1$s.</string>
|
||||
|
||||
|
@ -711,6 +716,7 @@
|
|||
<string name="installed_manga">Installed Manga</string>
|
||||
<string name="color_picker">Color Picker</string>
|
||||
<string name="random_selection">Random Selection</string>
|
||||
<string name="listed_in_library">Listed in Library</string>
|
||||
<string name="incognito_mode">Incognito Mode</string>
|
||||
<string name="appwidget_text">EXAMPLE</string>
|
||||
<string name="configure">Configure</string>
|
||||
|
@ -948,6 +954,8 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
|||
<string name="use_unique_theme_for_each_item_desc">Use color from media\'s banner</string>
|
||||
<string name="use_custom_theme_desc">Use your own color for the theme</string>
|
||||
<string name="color_picker_desc">Choose a color</string>
|
||||
<string name="hide_private">Hide private Media from home screen</string>
|
||||
<string name="hide_private_desc">Long click "Continue Watching" to access</string>
|
||||
<string name="torrent_addon">Torrent Add-on</string>
|
||||
<string name="enable_torrent">Enable Torrent</string>
|
||||
<string name="anime_downloader_addon">Anime Downloader Add-on</string>
|
||||
|
@ -959,6 +967,7 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
|||
<string name="install_addon">Install Add-on</string>
|
||||
<string name="download_addon_not_found">Add-on not found</string>
|
||||
<string name="image">Image</string>
|
||||
<string name="clear_history">Clear History</string>
|
||||
<string name="failed_ext_install_conflict">Failed to install extension due to conflict</string>
|
||||
<string name="reading">READING</string>
|
||||
<string name="watching">WATCHING</string>
|
||||
|
@ -1033,5 +1042,6 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
|||
<string name="bio_prompt_info_desc">Use your fingerprint or face to unlock the app</string>
|
||||
<string name="enable_forgot_password">Enable Forgot Password (hold clear button for 10 seconds)</string>
|
||||
<string name="hide_notification_dot">Hide Notification Dot</string>
|
||||
<string name="private_mode">Private</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<item name="elevationOverlayEnabled">false</item>
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:layoutDirection">ltr</item>
|
||||
<item name="android:windowContentTransitions">true</item>
|
||||
<item name="android:fontFamily">@font/poppins</item>
|
||||
<item name="shapeAppearanceLargeComponent">@style/ShapeAppearanceOverlay.Demo</item>
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Define your preferences here. For example: -->
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="some_key"
|
||||
android:title="Some Title" />
|
||||
z
|
||||
</PreferenceScreen>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue