From d39f4e1505716b85fa9b85531eab3beb0fe4f1e4 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Sat, 23 Jul 2022 23:15:15 -0300 Subject: [PATCH 01/50] Ajuste de fonte. --- .../view/ui/window/FloatingButtons.kt | 1 - .../view/ui/window/FloatingSubtitleReader.kt | 51 +++++++------- .../view/ui/window/FloatingWindowOcr.kt | 68 ++++++++++--------- 3 files changed, 63 insertions(+), 57 deletions(-) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingButtons.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingButtons.kt index 133b6965..89b403c0 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingButtons.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingButtons.kt @@ -39,7 +39,6 @@ class FloatingButtons constructor(private val context: Context, private val acti private var firstY: Int = 0 var isShowing = false - private var touchConsumedByMove = false private val mOnFlingListener = object : GestureDetector.SimpleOnGestureListener() { override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean { diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingSubtitleReader.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingSubtitleReader.kt index 8dba3003..d1cadf4f 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingSubtitleReader.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingSubtitleReader.kt @@ -330,31 +330,34 @@ class FloatingSubtitleReader constructor(private val context: Context, private v } private fun fixBoxBounds() { - if (layoutParams.x < 0) { - layoutParams.x = 0 - } else if (layoutParams.x + layoutParams.width > mRealDisplaySize.x) { - layoutParams.x = mRealDisplaySize.x - layoutParams.width - } - if (layoutParams.y < 0) { - layoutParams.y = 0 - } else if (layoutParams.y + layoutParams.height > mRealDisplaySize.y) { - layoutParams.y = mRealDisplaySize.y - layoutParams.height - } - if (layoutParams.width > mRealDisplaySize.x) { - layoutParams.width = mRealDisplaySize.x - } - if (layoutParams.height > mRealDisplaySize.y) { - layoutParams.height = mRealDisplaySize.y - } - if (isExpanded) { - if (layoutParams.width < minSize) - layoutParams.width = minSize - } else { - if (layoutParams.width < mMinimisedSize) - layoutParams.width = mMinimisedSize + with(layoutParams) { + if (x < 0) + x = 0 + else if (x + width > mRealDisplaySize.x) + x = mRealDisplaySize.x - width + + if (y < 0) + y = 0 + else if (y + height > mRealDisplaySize.y) + y = mRealDisplaySize.y - height + + if (width > mRealDisplaySize.x) + width = mRealDisplaySize.x + + if (height > mRealDisplaySize.y) + height = mRealDisplaySize.y + + if (isExpanded) { + if (width < minSize) + width = minSize + } else { + if (width < mMinimisedSize) + width = mMinimisedSize + } + + if (height < minSize) + height = minSize } - if (layoutParams.height < minSize) - layoutParams.height = minSize } diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingWindowOcr.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingWindowOcr.kt index 6b417706..b670aef4 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingWindowOcr.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingWindowOcr.kt @@ -90,17 +90,19 @@ class FloatingWindowOcr constructor(private val context: Context, private val ac private fun getDefaultParams(): WindowManager.LayoutParams { val params = WindowManager.LayoutParams() - params.width = context.resources.getDimension(R.dimen.floating_ocr_height).toInt() - params.height = context.resources.getDimension(R.dimen.floating_ocr_width).toInt() - params.type = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) - WindowManager.LayoutParams.TYPE_PHONE - else - WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - params.format = PixelFormat.TRANSLUCENT - params.gravity = Gravity.TOP or Gravity.LEFT - params.x = (mRealDisplaySize.x / 2) - (params.width / 2) - params.y = (mRealDisplaySize.y / 2) - (params.height / 2) + with(params) { + width = context.resources.getDimension(R.dimen.floating_ocr_height).toInt() + height = context.resources.getDimension(R.dimen.floating_ocr_width).toInt() + type = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) + WindowManager.LayoutParams.TYPE_PHONE + else + WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY + flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + format = PixelFormat.TRANSLUCENT + gravity = Gravity.TOP or Gravity.LEFT + x = (mRealDisplaySize.x / 2) - (width / 2) + y = (mRealDisplaySize.y / 2) - (height / 2) + } return params } @@ -260,27 +262,29 @@ class FloatingWindowOcr constructor(private val context: Context, private val ac } private fun fixBoxBounds() { - if (layoutParams.x < 0) { - layoutParams.x = 0 - } else if (layoutParams.x + layoutParams.width > mRealDisplaySize.x) { - layoutParams.x = mRealDisplaySize.x - layoutParams.width - } - if (layoutParams.y < 0) { - layoutParams.y = 0 - } else if (layoutParams.y + layoutParams.height > mRealDisplaySize.y) { - layoutParams.y = mRealDisplaySize.y - layoutParams.height - getStatusBarHeight() - } - if (layoutParams.width > mRealDisplaySize.x) { - layoutParams.width = mRealDisplaySize.x - } - if (layoutParams.height > mRealDisplaySize.y) { - layoutParams.height = mRealDisplaySize.y - } - if (layoutParams.width < minSize) { - layoutParams.width = minSize - } - if (layoutParams.height < minSize) { - layoutParams.height = minSize + with(layoutParams) { + if (x < 0) + x = 0 + else if (x + width > mRealDisplaySize.x) + x = mRealDisplaySize.x - width + + if (y < 0) + y = 0 + else if (y + height > mRealDisplaySize.y) + y = mRealDisplaySize.y - height - getStatusBarHeight() + + if (width > mRealDisplaySize.x) + width = mRealDisplaySize.x + + if (height > mRealDisplaySize.y) + height = mRealDisplaySize.y + + if (width < minSize) + width = minSize + + if (height < minSize) + height = minSize + } } From acba30734526f9c12c73969a74584515ec6412bf Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Sat, 23 Jul 2022 23:10:05 -0300 Subject: [PATCH 02/50] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20de=20consulta?= =?UTF-8?q?=20do=20MyAnimeList.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/listener/ApiListener.kt | 6 + .../service/tracker/ParseInformation.kt | 31 +++++ .../service/tracker/RetrofitClient.kt | 46 +++++++ .../service/tracker/mal/MyAnimeListEnum.kt | 81 ++++++++++++ .../tracker/mal/MyAnimeListMangaDetail.kt | 116 +++++++++++++++++ .../tracker/mal/MyAnimeListMangaList.kt | 44 +++++++ .../service/tracker/mal/MyAnimeListService.kt | 88 +++++++++++++ .../service/tracker/mal/MyAnimeListTracker.kt | 117 ++++++++++++++++++ .../service/tracker/mal/OAuth.kt | 15 +++ .../service/tracker/mal/User.kt | 26 ++++ .../util/secrets/PkceUtil.kt | 15 +++ .../util/secrets/Secrets.kt | 8 +- .../ui/manga_detail/MangaDetailFragment.kt | 40 +----- .../ui/manga_detail/MangaDetailViewModel.kt | 55 +++++--- app/src/main/res/values-en/strings.xml | 1 + app/src/main/res/values-pt-rBR/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 17 files changed, 629 insertions(+), 62 deletions(-) create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/listener/ApiListener.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/ParseInformation.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/RetrofitClient.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListEnum.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaDetail.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaList.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListService.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListTracker.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/OAuth.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/User.kt create mode 100644 app/src/main/java/br/com/fenix/bilingualmangareader/util/secrets/PkceUtil.kt diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/listener/ApiListener.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/listener/ApiListener.kt new file mode 100644 index 00000000..1dc0afc5 --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/listener/ApiListener.kt @@ -0,0 +1,6 @@ +package br.com.fenix.bilingualmangareader.service.listener + +interface ApiListener { + fun onSuccess(result: T) + fun onFailure(message: String) +} \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/ParseInformation.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/ParseInformation.kt new file mode 100644 index 00000000..bd53ecf7 --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/ParseInformation.kt @@ -0,0 +1,31 @@ +package br.com.fenix.bilingualmangareader.service.tracker + +import br.com.fenix.bilingualmangareader.model.entity.Information +import br.com.fenix.bilingualmangareader.service.tracker.mal.MalMangaDetail + +class ParseInformation { + companion object { + fun getInformation(list: List): MutableList { + val newList = mutableListOf() + for (item in list) + newList.add(getInformation(item)) + + newList.removeIf { + it.title.isEmpty() + } + + return newList + } + + fun getInformation(item: T): Information { + return when (item) { + is MalMangaDetail -> Information(item as MalMangaDetail) + else -> Information() + } + } + + fun getInformation(item: MalMangaDetail): Information { + return Information(item) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/RetrofitClient.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/RetrofitClient.kt new file mode 100644 index 00000000..4661508f --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/RetrofitClient.kt @@ -0,0 +1,46 @@ +package br.com.fenix.bilingualmangareader.service.tracker + +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +class RetrofitClient private constructor() { + companion object { + private lateinit var INSTANCE: Retrofit + private lateinit var INSTANCEOAUTH: Retrofit + private const val BASE_OAUTH_Url = "https://myanimelist.net/v1/oauth2/" + private const val BASE_API_URL = "https://api.myanimelist.net/v2/" + private fun getRetrofitInstance(): Retrofit { + if (!::INSTANCE.isInitialized) { + synchronized(RetrofitClient::class) { + val httpClient = OkHttpClient.Builder() + INSTANCE = Retrofit.Builder() + .baseUrl(BASE_API_URL) + .client(httpClient.build()) + .addConverterFactory(GsonConverterFactory.create()) + .build() + } + } + return INSTANCE + } + + fun getService(service: Class): T { + return getRetrofitInstance().create(service) + } + + fun getOAuth(service: Class): T { + if (!::INSTANCEOAUTH.isInitialized) { + synchronized(RetrofitClient::class) { + val httpClient = OkHttpClient.Builder() + INSTANCEOAUTH = Retrofit.Builder() + .baseUrl(BASE_OAUTH_Url) + .client(httpClient.build()) + .addConverterFactory(GsonConverterFactory.create()) + .build() + } + } + return INSTANCEOAUTH.create(service) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListEnum.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListEnum.kt new file mode 100644 index 00000000..b5e1d693 --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListEnum.kt @@ -0,0 +1,81 @@ +package br.com.fenix.bilingualmangareader.service.tracker.mal + +import com.google.gson.annotations.SerializedName + +enum class NSFW { + @SerializedName("white") + WHITE, + + @SerializedName("gray") + GRAY, + + @SerializedName("black") + BLACK +} + +enum class STATUS { + @SerializedName("finished") + FINISHED, + + @SerializedName("currently_publishing") + CURRENTLY_PUBLISHING, + + @SerializedName("not_yet_published") + NOT_YET_PUBLISHED +} + +enum class MEDIA { + @SerializedName("unknown") + UNKNOWN, + + @SerializedName("manga") + MANGA, + + @SerializedName("novel") + NOVEL, + + @SerializedName("one_shot") + ONE_SHOT, + + @SerializedName("doujinshi") + DOUJINSHI, + + @SerializedName("manhwa") + MANHWA, + + @SerializedName("manhua") + MANHUA, + + @SerializedName("oel") + OEL, +} + +enum class RANKING { + @SerializedName("all") + ALL, + + @SerializedName("manga") + MANGA, + + @SerializedName("novels") + NOVELS, + + @SerializedName("oneshots") + ONESHOTS, + + @SerializedName("doujin") + DOUJIN, + + @SerializedName("manhwa") + MANHWA, + + @SerializedName("manhua") + MANHUA, + + @SerializedName("bypopularity") + BYPOPULARITY, + + @SerializedName("favorite") + FAVORITE +} + diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaDetail.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaDetail.kt new file mode 100644 index 00000000..7851b781 --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaDetail.kt @@ -0,0 +1,116 @@ +package br.com.fenix.bilingualmangareader.service.tracker.mal + +import com.google.gson.annotations.SerializedName + +data class MalMangaDetail( + @SerializedName("id") + val id: Int, + @SerializedName("title") + val title: String = "", + @SerializedName("main_picture") + val mainPicture: MalPicture?, + @SerializedName("alternative_titles") + val alternativeTitles: MalAlternativeTitles?, + @SerializedName("start_date") + val startDate: String?, + @SerializedName("end_date") + val endDate: String?, + @SerializedName("synopsis") + val synopsis: String?, + @SerializedName("mean") + val mean: String?, + @SerializedName("rank") + val rank: String?, + @SerializedName("popularity") + val popularity: Int = 0, + @SerializedName("num_list_users") + val numListUsers: Int = 0, + @SerializedName("num_scoring_users") + val numScoringUsers: Int = 0, + @SerializedName("nsfw") + val nsfw: NSFW?, + @SerializedName("genres") + val genres: List?, + @SerializedName("created_at") + val createdAt: String?, + @SerializedName("updated_at") + val updatedAt: String?, + @SerializedName("media_type") + val mediaType: MEDIA?, + @SerializedName("status") + val status: STATUS?, + @SerializedName("my_list_status") + val myListStatus: List?, + @SerializedName("num_volumes") + val volumes: Int = 0, + @SerializedName("num_chapters") + val chapters: Int = 0, + @SerializedName("authors") + val authors: List?, + @SerializedName("pictures") + val pictures: List? +) + + +data class MalPicture( + @SerializedName("large") + val large: String, + @SerializedName("medium") + val medium: String +) + +data class MalAlternativeTitles( + @SerializedName("synonyms") + val synonyms: List, + @SerializedName("en") + val english: String, + @SerializedName("ja") + val japanese: String +) + +data class MalGenres( + @SerializedName("id") + val id: Int, + @SerializedName("name") + val name: String +) + +data class MalAuthors( + @SerializedName("id") + val id: Int, + @SerializedName("first_name") + val firstName: String, + @SerializedName("last_name") + val lastName: String, + @SerializedName("role") + val role: String +) + +data class MalStatus( + @SerializedName("status") + val status: String?, + @SerializedName("score") + val score: Int, + @SerializedName("num_volumes_read") + val numVolumesRead: Int, + @SerializedName("num_chapters_read") + val numChaptersRead: Int, + @SerializedName("is_rereading") + val isRereading: Boolean, + @SerializedName("start_date") + val startDate: String?, + @SerializedName("finish_date") + val finishDate: String?, + @SerializedName("priority") + val priority: Int, + @SerializedName("num_times_reread") + val numTimesReread: Int, + @SerializedName("reread_value") + val reread_value: Int, + @SerializedName("tags") + val tags: List, + @SerializedName("comments") + val comments: String, + @SerializedName("updated_at") + val updatedAt: String +) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaList.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaList.kt new file mode 100644 index 00000000..2ed5be3a --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaList.kt @@ -0,0 +1,44 @@ +package br.com.fenix.bilingualmangareader.service.tracker.mal + +import com.google.gson.annotations.SerializedName +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +data class MalMangaList( + @SerializedName("data") + val data: List, + @SerializedName("padding") + val padding: Padding, +) + +data class Padding( + @SerializedName("previous") + val previous: String, + @SerializedName("next") + val next: String +) + +data class Node( + @SerializedName("node") + val item: MalMangaDetail +) + +class MalTransform { + companion object { + fun getList(list: List): List = + list.map { it.item } + + private val formatDates = listOf("yyyy-MM-dd", "yyyy-MM", "yyyy") + fun getDate(date: String): Date? { + for (format in formatDates) { + try { + return SimpleDateFormat(format).parse(date) + } catch (e: ParseException) { + } + } + return null + } + } +} + diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListService.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListService.kt new file mode 100644 index 00000000..929c6604 --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListService.kt @@ -0,0 +1,88 @@ +package br.com.fenix.bilingualmangareader.service.tracker.mal + +import retrofit2.Call +import retrofit2.http.* + +interface MyAnimeListService { + + companion object { + const val FIELDS = "id,title,main_picture,alternative_titles,start_date,end_date,synopsis,mean,rank,popularity,num_list_users,num_scoring_users,nsfw,created_at,updated_at,media_type,status,genres,my_list_status,num_volumes,num_chapters,authors{first_name,last_name},pictures,background,related_anime,related_manga,recommendations,serialization{name}" + } + + @GET("authorize") + fun auth( + @Query("client_id") idClient: String, + @Query("code_challenge") challenge: String, + @Query("response_type") authorization: String = "code" + ): Call + + @POST("token") + @FormUrlEncoded + fun refreshToken( + @Field("client_id") idClient: String, + @Field("refresh_token") refreshToken: String, + @Field("grant_type") type: String = "refresh_token" + ): Call + + @POST("token") + @FormUrlEncoded + fun login( + @Field("client_id") idClient: String, + @Field("code") authCode: String, + @Field("code_verifier") codeVerifier: String = "", + @Field("grant_type") authorization: String = "authorization_code" + ): Call + + //Example 'https://api.myanimelist.net/v2/manga/2?fields=id,title,main_picture,alternative_titles,start_date,end_date,synopsis,mean,rank,popularity,num_list_users,num_scoring_users,nsfw,created_at,updated_at,media_type,status,genres,my_list_status,num_volumes,num_chapters,authors{first_name,last_name},pictures,background,related_anime,related_manga,recommendations,serialization{name}' + @GET("manga/{manga_id}") + fun getMangaDetail( + @Header("Authorization") token: String?, + @Header("X-MAL-CLIENT-ID") idClient: String?, + @Path("manga_id") idManga: Long, + @Query("fields", encoded = true) fields: String = FIELDS + ): Call + + // Query set in url condition + @GET("manga") + fun getListManga( + @Header("Authorization") token: String?, + @Header("X-MAL-CLIENT-ID") idClient: String?, + @Query("q") search: String, + @Query("limit") limit: Int = 250, + @Query("offset") offset: Int? = null, + @Query("fields", encoded = true) fields: String = FIELDS + ): Call + + @GET("users/{user_name}") + fun getUserMangaList( + @Header("Authorization") token: String?, + @Header("X-MAL-CLIENT-ID") idClient: String?, + @Path("user_name") userName: String, + @Query("q") search: String, + @Query("status") status: String = "", + @Query("sort") sort: String = "", + @Query("limit") limit: Int = 100, + @Query("offset") offset: Int = 0, + @Query("fields", encoded = true) fields: String = FIELDS, + @Query("nsfw") nsfw: Boolean = false + ): Call + + @POST("manga/{manga_id}/my_list_status") + @FormUrlEncoded + fun updateMangaList( + @Header("Authorization") token: String, + @Path("manga_id") idManga: Long, + @Field("is_rereading") isRereading: Boolean = false, + @Field("score") score: Int = 0, + @Field("start_date", encoded = true) startDate: String = "", + @Field("finish_date", encoded = true) finishDate: String = "", + @Field("num_volumes_read") volumesRead: Int = 0, + @Field("num_chapters_read") chaptersRead: Int = 0, + @Field("priority") priority: Int = 0, + @Field("num_times_reread") timesReread: Int = 0, + @Field("reread_value") reread: Int = 0, + @Field("tags") tags: String = "", + @Field("comments") comments: String = "" + ): Call + +} \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListTracker.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListTracker.kt new file mode 100644 index 00000000..7e457821 --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListTracker.kt @@ -0,0 +1,117 @@ +package br.com.fenix.bilingualmangareader.service.tracker.mal + +import android.content.Context +import br.com.fenix.bilingualmangareader.R +import br.com.fenix.bilingualmangareader.service.listener.ApiListener +import br.com.fenix.bilingualmangareader.service.tracker.RetrofitClient +import br.com.fenix.bilingualmangareader.util.secrets.PkceUtil +import br.com.fenix.bilingualmangareader.util.secrets.Secrets +import org.slf4j.LoggerFactory +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class MyAnimeListTracker(var mContext: Context) { + + private val mLOGGER = LoggerFactory.getLogger(MyAnimeListTracker::class.java) + + private val mMyAnimeListAuth = RetrofitClient.getOAuth(MyAnimeListService::class.java) + private val mMyAnimeList = RetrofitClient.getService(MyAnimeListService::class.java) + private var idClient: String = Secrets.getSecrets(mContext).getMyAnimeListClientId() + private var token: String? = null + private var oAuth: OAuth? = null + + private fun getIdClient() = + if (token != null) null else idClient + + private inline fun validToken(authCode: String, listener: ApiListener, crossinline function: () -> Unit) { + if (token == null || oAuth == null || oAuth!!.isExpired()) { + val call = if (token != null) + mMyAnimeListAuth.refreshToken(Secrets.getSecrets(mContext).getMyAnimeListClientId(), authCode, token!!) + else + mMyAnimeListAuth.auth(Secrets.getSecrets(mContext).getMyAnimeListClientId(), PkceUtil.generateCodeVerifier()) + + call.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + println(response) + if (response.code() == 200) { + oAuth = response.body() + token = response.body()?.access_token ?: "" + if (token != null && token!!.isNotEmpty()) + function() + } else + listener.onFailure(response.raw().toString()) + } + + override fun onFailure(call: Call, t: Throwable) { + mLOGGER.error(t.message, t.stackTrace) + listener.onFailure(mContext.getString(R.string.api_error)) + } + }) + } else + function() + } + + fun login(email: String, passWord: String, listener: ApiListener) { + val call = mMyAnimeList.login(email, passWord) + call.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.code() == 200) + response.body()?.let { listener.onSuccess(it) } + else + listener.onFailure(response.raw().toString()) + } + + override fun onFailure(call: Call, t: Throwable) { + mLOGGER.error(t.message, t.stackTrace) + listener.onFailure(mContext.getString(R.string.api_error)) + } + }) + } + + fun updateUserManga(search: String, listener: ApiListener>) { + validToken("", listener) { + + } + } + + fun getListManga(search: String, listener: ApiListener>) { + val call = mMyAnimeList.getListManga(token, getIdClient(), search, limit = 20) + call.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.code() == 200) + response.body()?.let { listener.onSuccess(MalTransform.getList(it.data)) } + else + listener.onFailure(response.raw().toString()) + } + + override fun onFailure(call: Call, t: Throwable) { + mLOGGER.error(t.message, t.stackTrace) + listener.onFailure(mContext.getString(R.string.api_error)) + } + + }) + } + + fun getListManga(search: String, listener: ApiListener>, vararg fields: String) { + val call = mMyAnimeList.getListManga(token, getIdClient(), search, fields = fields.joinToString(",")) + call.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.code() == 200) + response.body()?.let { + listener.onSuccess(MalTransform.getList(it.data)) + } + else + listener.onFailure(response.raw().toString()) + } + + override fun onFailure(call: Call, t: Throwable) { + mLOGGER.error(t.message, t.stackTrace) + listener.onFailure(mContext.getString(R.string.api_error)) + } + + }) + + } + +} \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/OAuth.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/OAuth.kt new file mode 100644 index 00000000..a45c3d47 --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/OAuth.kt @@ -0,0 +1,15 @@ +package br.com.fenix.bilingualmangareader.service.tracker.mal + +import java.io.Serializable + +data class OAuth( + val refresh_token: String, + val access_token: String, + val token_type: String, + val created_at: Long = System.currentTimeMillis(), + val expires_in: Long, +) : Serializable { + + fun isExpired() = + System.currentTimeMillis() > created_at + (expires_in * 1000) +} diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/User.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/User.kt new file mode 100644 index 00000000..1362793d --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/User.kt @@ -0,0 +1,26 @@ +package br.com.fenix.bilingualmangareader.service.tracker.mal + +import com.google.gson.annotations.SerializedName + +data class User( + @SerializedName("id") + val id: Int, + @SerializedName("name") + val name: String, + @SerializedName("picture") + val picture: String, + @SerializedName("gender") + val gender: String?, + @SerializedName("birthday") + val birthday: String?, + @SerializedName("location") + val location: String?, + @SerializedName("joined_at") + val joinedAt: String, + //@SerializedName("anime_statistics") + //lateinit var anime_statistics object or null + @SerializedName("time_zone") + val timeZone: String?, + @SerializedName("is_supporter") + val isSupporter: Boolean? +) \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/util/secrets/PkceUtil.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/util/secrets/PkceUtil.kt new file mode 100644 index 00000000..ff305996 --- /dev/null +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/util/secrets/PkceUtil.kt @@ -0,0 +1,15 @@ +package br.com.fenix.bilingualmangareader.util.secrets + +import android.util.Base64 +import java.security.SecureRandom + +object PkceUtil { + + private const val PKCE_BASE64_ENCODE_SETTINGS = Base64.NO_WRAP or Base64.NO_PADDING or Base64.URL_SAFE + + fun generateCodeVerifier(): String { + val codeVerifier = ByteArray(50) + SecureRandom().nextBytes(codeVerifier) + return Base64.encodeToString(codeVerifier, PKCE_BASE64_ENCODE_SETTINGS) + } +} \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/util/secrets/Secrets.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/util/secrets/Secrets.kt index 4c6bab3c..60322822 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/util/secrets/Secrets.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/util/secrets/Secrets.kt @@ -26,7 +26,7 @@ class Secrets { } } - private var ANIME_LIST_CLIENT_ID: String = "" + private var MY_ANIME_LIST_CLIENT_ID: String = "" init { try { @@ -35,15 +35,15 @@ class Secrets { val inputStream: InputStream = assetManager.open("secrets.properties") properties.load(inputStream) - ANIME_LIST_CLIENT_ID = properties.getProperty("ANIME_LIST_CLIENT_ID") + MY_ANIME_LIST_CLIENT_ID = properties.getProperty("ANIME_LIST_CLIENT_ID") } catch (e: IOException) { e.printStackTrace() mLOGGER.error("Error to read secrets", e) } } - fun getAnimeListClientId(): String { - return ANIME_LIST_CLIENT_ID + fun getMyAnimeListClientId(): String { + return MY_ANIME_LIST_CLIENT_ID } } \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt index b95b65a7..17cd1def 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt @@ -168,7 +168,7 @@ class MangaDetailFragment(private var mManga: Manga?) : Fragment() { override fun onResume() { super.onResume() - getInformation() + mViewModel.getInformation() } private fun observer() { @@ -298,44 +298,6 @@ class MangaDetailFragment(private var mManga: Manga?) : Fragment() { } - private fun getInformation() { - //MyAnimeList does not run on older versions - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) - return - - var name = mViewModel.manga.value?.title ?: "" - - if (name.isNotEmpty()) { - name = Util.getNameFromMangaTitle(name).replace(" ", "%") - - CoroutineScope(Dispatchers.IO).launch { - try { - var search: List? = null - val deferred = async { - try { - val mal: MyAnimeList = MyAnimeList.withClientID(Secrets.getSecrets(requireContext()).getAnimeListClientId()) - search = mal.manga - .withQuery(name) - .includeNSFW(false) - .search() - - } catch (e: Exception) { - mLOGGER.error("Error to search manga info", e) - } - } - deferred.await() - withContext(Dispatchers.Main) { - if (!search.isNullOrEmpty()) - mViewModel.setInformation(search!!) - } - } catch (e: Exception) { - mLOGGER.error("Error to load manga info", e) - } - } - } - - } - private fun deleteFile() { val manga = mViewModel.manga.value ?: return AlertDialog.Builder(requireActivity(), R.style.AppCompatAlertDialogStyle) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailViewModel.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailViewModel.kt index 6447c99c..f80f7ccb 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailViewModel.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailViewModel.kt @@ -7,18 +7,24 @@ import androidx.lifecycle.MutableLiveData import br.com.fenix.bilingualmangareader.model.entity.FileLink import br.com.fenix.bilingualmangareader.model.entity.Information import br.com.fenix.bilingualmangareader.model.entity.Manga +import br.com.fenix.bilingualmangareader.service.listener.ApiListener import br.com.fenix.bilingualmangareader.service.parses.ParseFactory import br.com.fenix.bilingualmangareader.service.parses.RarParse import br.com.fenix.bilingualmangareader.service.repository.FileLinkRepository import br.com.fenix.bilingualmangareader.service.repository.MangaRepository +import br.com.fenix.bilingualmangareader.service.tracker.ParseInformation +import br.com.fenix.bilingualmangareader.service.tracker.mal.MyAnimeListTracker +import br.com.fenix.bilingualmangareader.service.tracker.mal.MalMangaDetail import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts import br.com.fenix.bilingualmangareader.util.helpers.Util -import com.kttdevelopment.mal4j.manga.MangaPreview +import org.slf4j.LoggerFactory import java.io.File import java.time.LocalDateTime class MangaDetailViewModel(application: Application) : AndroidViewModel(application) { + private val mLOGGER = LoggerFactory.getLogger(MangaDetailViewModel::class.java) + private val mContext = application.applicationContext private val mMangaRepository: MangaRepository = MangaRepository(mContext) private val mFileLinkRepository: FileLinkRepository = FileLinkRepository(mContext) @@ -43,6 +49,8 @@ class MangaDetailViewModel(application: Application) : AndroidViewModel(applicat private var mInformationRelations = MutableLiveData>(mutableListOf()) val informationRelations: LiveData> = mInformationRelations + private val mTracker = MyAnimeListTracker(mContext) + fun setManga(manga: Manga) { mManga.value = manga @@ -66,30 +74,39 @@ class MangaDetailViewModel(application: Application) : AndroidViewModel(applicat } } + fun getInformation() { + var name = mManga.value?.title ?: "" - private val PATTERN = Regex("[^\\w\\s]") - fun setInformation(mangas: List) { - var information: Information? = null - val name = Util.getNameFromMangaTitle(mManga.value?.title ?: "").replace(PATTERN, "") - val manga = mangas.find { - it.title.replace(PATTERN, "").trim().equals(name, true) || - it.alternativeTitles.japanese.trim().equals(name, true) || - it.alternativeTitles.english.trim().equals(name, true) || - it.alternativeTitles.synonyms.any { sy -> sy.trim().equals(name, true) } - } + if (name.isEmpty()) + return - if (manga != null) - information = Information(manga) + name = Util.getNameFromMangaTitle(name).replace(" ", "%") + mTracker.getListManga(name, object : ApiListener> { + override fun onSuccess(result: List) { + setInformation(result) + } - mInformation.value = information + override fun onFailure(message: String) { + mLOGGER.error("Error to search manga info", message) + } + }) - val relations: MutableList = mutableListOf() - for (aux in mangas) { - if (aux != manga) - relations.add(Information(aux)) + } + + private val PATTERN = Regex("[^\\w\\s]") + fun setInformation(mangas: List) { + val list = ParseInformation.getInformation(mangas) + + val name = Util.getNameFromMangaTitle(mManga.value?.title ?: "").replace(PATTERN, "") + + mInformation.value = list.find { + it.title.replace(PATTERN, "").trim().equals(name, true) || + it.alternativeTitles.contains(name, true) } + if (mInformation.value != null) + list.remove(mInformation.value) - mInformationRelations.value = relations + mInformationRelations.value = list } fun getPage(folder: String): Int { diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index e1484549..5c8a1903 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -14,6 +14,7 @@ It not possible to obtain the access permissions to the informed folder, please obtain access in android settings. unknown + Error connecting to API Search diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index cfb908ab..4ea47d92 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -14,6 +14,7 @@ Não foi possível obter a permissão de acesso a pasta informada, por favor libere o acesso na configuração do android. desconhecido + Error connecting to API Procurar diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 115b2629..b26d4986 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,6 +13,7 @@ It not possible to obtain the access permissions to the informed folder, please obtain access in android settings. unknown + Error connecting to API Search From c21ec47a89e9327ff56a4876a35f1d9b334b3293 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Sat, 23 Jul 2022 23:14:32 -0300 Subject: [PATCH 03/50] =?UTF-8?q?Remo=C3=A7=C3=A3o=20da=20biblioteca=20do?= =?UTF-8?q?=20MyAnimeList.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 6 ++- .../model/entity/Information.kt | 43 +++++++++++-------- .../ui/manga_detail/MangaDetailFragment.kt | 7 --- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f7b2446b..d95f9a32 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -80,8 +80,12 @@ dependencies { implementation 'cz.adaptech:tesseract4android:4.1.1' implementation 'com.google.android.gms:play-services-mlkit-text-recognition:18.0.0' + // API CONECTION + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.retrofit2:converter-gson:2.9.0' + // MANGA INFO - implementation 'com.kttdevelopment:mal4j:2.8.1' + //implementation 'com.kttdevelopment:mal4j:2.8.1' // TEST testImplementation 'junit:junit:4.13.2' diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Information.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Information.kt index b079accd..8107f74b 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Information.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Information.kt @@ -1,6 +1,7 @@ package br.com.fenix.bilingualmangareader.model.entity -import com.kttdevelopment.mal4j.manga.MangaPreview +import br.com.fenix.bilingualmangareader.service.tracker.mal.MalMangaDetail +import br.com.fenix.bilingualmangareader.service.tracker.mal.MalTransform import java.util.* class Information( @@ -13,7 +14,7 @@ class Information( constructor() : this("", null, "", "", "", "", "", "", "", null, null, "", "") - constructor(manga: MangaPreview) : this() { + constructor(manga: MalMangaDetail) : this() { setManga(manga) } @@ -32,29 +33,35 @@ class Information( var authors: String = authors var origin: String = "" - fun setManga(manga: MangaPreview) { - this.link = "https://myanimelist.net/manga/" + manga.id - this.imageLink = manga.mainPicture.mediumURL + fun setManga(manga: MalMangaDetail) { + this.link = "https://myanimelist.net/manga/${manga.id}" + this.imageLink = manga.mainPicture?.medium.toString() this.title = manga.title this.alternativeTitles = "" - if (manga.alternativeTitles.english.isNotEmpty()) - this.alternativeTitles += manga.alternativeTitles.english + ", " - if (manga.alternativeTitles.japanese.isNotEmpty()) - this.alternativeTitles += manga.alternativeTitles.japanese + ", " - if (manga.alternativeTitles.synonyms.isNotEmpty()) - this.alternativeTitles += manga.alternativeTitles.synonyms + ", " + + manga.alternativeTitles?.let { + if (it.english.isNotEmpty()) + this.alternativeTitles += it.english + ", " + if (it.japanese.isNotEmpty()) + this.alternativeTitles += it.japanese + ", " + if (it.synonyms.isNotEmpty()) + this.alternativeTitles += it.synonyms + ", " + + this.synonyms = it.synonyms.toString() + } this.alternativeTitles = this.alternativeTitles.substringBeforeLast(",").plus(".") - this.synopsis = manga.synopsis - this.synonyms = manga.synopsis + manga.synopsis?.let { this.synopsis = it } this.volumes = manga.volumes.toString() this.chapters = manga.chapters.toString() - this.status = manga.status.name - this.startDate = manga.startDate - this.endDate = manga.endDate - this.genres = manga.genres.joinToString { it.name } - this.authors = manga.authors.joinToString { it.firstName + " " + it.lastName + "(" + it.role + ")" } + manga.status?.let { this.status = it.name } + + manga.startDate?.let { if (it.isNotEmpty()) this.startDate = MalTransform.getDate(it) } + manga.endDate?.let { if (it.isNotEmpty()) this.endDate = MalTransform.getDate(it) } + + this.genres = manga.genres?.joinToString { it.name } ?: "" + this.authors = manga.authors?.joinToString { it.firstName + " " + it.lastName + "(" + it.role + ")" } ?: "" this.origin = MY_ANIME_LIST } } \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt index 17cd1def..c71bcec8 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/manga_detail/MangaDetailFragment.kt @@ -2,7 +2,6 @@ package br.com.fenix.bilingualmangareader.view.ui.manga_detail import android.content.Intent import android.net.Uri -import android.os.Build import android.os.Bundle import android.text.Html import android.view.LayoutInflater @@ -10,8 +9,6 @@ import android.view.View import android.view.ViewGroup import android.widget.* import androidx.appcompat.app.AlertDialog -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.substring import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager @@ -24,13 +21,9 @@ import br.com.fenix.bilingualmangareader.service.controller.ImageCoverController import br.com.fenix.bilingualmangareader.service.listener.InformationCardListener import br.com.fenix.bilingualmangareader.util.constants.GeneralConsts import br.com.fenix.bilingualmangareader.util.helpers.Util -import br.com.fenix.bilingualmangareader.util.secrets.Secrets import br.com.fenix.bilingualmangareader.view.adapter.manga_detail.InformationRelatedCardAdapter import br.com.fenix.bilingualmangareader.view.ui.reader.ReaderActivity import com.google.android.material.button.MaterialButton -import com.kttdevelopment.mal4j.MyAnimeList -import com.kttdevelopment.mal4j.manga.MangaPreview -import kotlinx.coroutines.* import org.slf4j.LoggerFactory import java.time.LocalDateTime From 8165314b86ff95235b45ee83b9c13e24eb67c680 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Sun, 24 Jul 2022 11:43:07 -0300 Subject: [PATCH 04/50] Adicionado tempo para erro de timeout. --- .../bilingualmangareader/service/tracker/RetrofitClient.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/RetrofitClient.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/RetrofitClient.kt index 4661508f..4711fc8a 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/RetrofitClient.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/RetrofitClient.kt @@ -3,6 +3,7 @@ package br.com.fenix.bilingualmangareader.service.tracker import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory +import java.util.concurrent.TimeUnit class RetrofitClient private constructor() { companion object { @@ -14,6 +15,8 @@ class RetrofitClient private constructor() { if (!::INSTANCE.isInitialized) { synchronized(RetrofitClient::class) { val httpClient = OkHttpClient.Builder() + httpClient.readTimeout(20, TimeUnit.SECONDS) + httpClient.connectTimeout(20, TimeUnit.SECONDS) INSTANCE = Retrofit.Builder() .baseUrl(BASE_API_URL) .client(httpClient.build()) From 37c0b59668f2aa9e31c9638a2295b8d29650d281 Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Sun, 24 Jul 2022 11:43:26 -0300 Subject: [PATCH 05/50] Adicionando monitoramento. --- .../util/constants/GeneralConsts.kt | 4 ++ .../view/ui/configuration/ConfigFragment.kt | 58 +++++++++++++--- .../main/res/drawable/ic_tracker_checked.xml | 5 ++ app/src/main/res/layout/fragment_config.xml | 64 ++++++++++++++++++ .../main/res/mipmap-hdpi/ic_MyAnimeList.png | Bin 0 -> 3474 bytes .../main/res/mipmap-mdpi/ic_MyAnimeList.png | Bin 0 -> 2437 bytes .../main/res/mipmap-xxhdpi/ic_MyAnimeList.png | Bin 0 -> 2932 bytes .../res/mipmap-xxxhdpi/ic_MyAnimeList.png | Bin 0 -> 1801 bytes app/src/main/res/values-en/strings.xml | 4 ++ app/src/main/res/values-pt-rBR/strings.xml | 4 ++ app/src/main/res/values/dimens.xml | 3 + app/src/main/res/values/strings.xml | 4 ++ 12 files changed, 135 insertions(+), 11 deletions(-) create mode 100644 app/src/main/res/drawable/ic_tracker_checked.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_MyAnimeList.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_MyAnimeList.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_MyAnimeList.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_MyAnimeList.png diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/util/constants/GeneralConsts.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/util/constants/GeneralConsts.kt index 3aab73c2..05f7629e 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/util/constants/GeneralConsts.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/util/constants/GeneralConsts.kt @@ -86,6 +86,10 @@ class GeneralConsts private constructor() { const val USE_DUAL_PAGE_CALCULATE = "USE_DUAL_PAGE_CALCULATE" const val USE_PAGE_PATH_FOR_LINKED = "USE_PAGE_PATH_FOR_LINKED" } + + object MONITORING { + const val MY_ANIME_LIST = "MONITORING_MY_ANIME_LIST" + } } object TAG { diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/configuration/ConfigFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/configuration/ConfigFragment.kt index ba7249eb..6deee1c7 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/configuration/ConfigFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/configuration/ConfigFragment.kt @@ -7,9 +7,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.AdapterView -import android.widget.ArrayAdapter -import android.widget.AutoCompleteTextView +import android.widget.* import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import br.com.fenix.bilingualmangareader.R @@ -51,6 +49,9 @@ class ConfigFragment : Fragment() { private lateinit var mUseDualPageCalculate: SwitchMaterial private lateinit var mUsePathNameForLinked: SwitchMaterial + private lateinit var mMalMonitoring: LinearLayout + private lateinit var mMalMonitoringChecked: ImageView + private var mDateSelect: String = GeneralConsts.CONFIG.DATA_FORMAT[0] private val mDatePattern = GeneralConsts.CONFIG.DATA_FORMAT private var mPageModeSelect: PageMode = PageMode.Comics @@ -91,6 +92,9 @@ class ConfigFragment : Fragment() { mUseDualPageCalculate = view.findViewById(R.id.switch_use_dual_page_calculate) mUsePathNameForLinked = view.findViewById(R.id.switch_use_path_name_for_linked) + mMalMonitoring = view.findViewById(R.id.tracker_my_anime_list) + mMalMonitoringChecked = view.findViewById(R.id.tracker_checked) + mLibraryPathAutoComplete.setOnClickListener { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) intent.addCategory(Intent.CATEGORY_DEFAULT) @@ -203,6 +207,8 @@ class ConfigFragment : Fragment() { GeneralConsts.CONFIG.DATA_FORMAT[0] } + mMalMonitoring.setOnClickListener { changeMonitoring() } + loadConfig() } @@ -294,14 +300,21 @@ class ConfigFragment : Fragment() { mUsePathNameForLinked.isChecked ) + this.putBoolean( + GeneralConsts.KEYS.MONITORING.MY_ANIME_LIST, + mMalMonitoringChecked.visibility == View.VISIBLE + ) + this.commit() } - mLOGGER.info("Save prefer CONFIG:" + "\n[Library] Path " + mLibraryPath.editText?.text + - " - Order " + mLibraryOrder.editText?.text + - "\n[SubTitle] Language " + mDefaultSubtitleLanguage.editText?.text + - " - Translate " + mDefaultSubtitleTranslate.editText?.text + - "\n[System] Format Data " + mSystemFormatDate.editText?.text) + mLOGGER.info( + "Save prefer CONFIG:" + "\n[Library] Path " + mLibraryPath.editText?.text + + " - Order " + mLibraryOrder.editText?.text + + "\n[SubTitle] Language " + mDefaultSubtitleLanguage.editText?.text + + " - Translate " + mDefaultSubtitleTranslate.editText?.text + + "\n[System] Format Data " + mSystemFormatDate.editText?.text + ) } @@ -380,14 +393,37 @@ class ConfigFragment : Fragment() { ) mUseDualPageCalculate.isChecked = sharedPreferences.getBoolean( - GeneralConsts.KEYS.PAGE_LINK.USE_DUAL_PAGE_CALCULATE, - false - ) + GeneralConsts.KEYS.PAGE_LINK.USE_DUAL_PAGE_CALCULATE, + false + ) mUsePathNameForLinked.isChecked = sharedPreferences.getBoolean( GeneralConsts.KEYS.PAGE_LINK.USE_PAGE_PATH_FOR_LINKED, false ) + mMalMonitoringChecked.visibility = if (sharedPreferences.getBoolean( + GeneralConsts.KEYS.MONITORING.MY_ANIME_LIST, + false + ) + ) View.VISIBLE else View.GONE + + } + + private fun changeMonitoring() { + if (mMalMonitoringChecked.visibility == View.GONE) { + + } else { + val dialog: AlertDialog = + AlertDialog.Builder(requireActivity(), R.style.AppCompatAlertDialogStyle) + .setTitle(getString(R.string.library_menu_delete)) + .setMessage(getString(R.string.config_title_monitoring_disconnect,getString(R.string.config_title_monitoring_mal))) + .setPositiveButton( + R.string.action_disconnect + ) { _, _ -> + mMalMonitoringChecked.visibility = View.GONE + }.create() + dialog.show() + } } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_tracker_checked.xml b/app/src/main/res/drawable/ic_tracker_checked.xml new file mode 100644 index 00000000..2501e9fd --- /dev/null +++ b/app/src/main/res/drawable/ic_tracker_checked.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/fragment_config.xml b/app/src/main/res/layout/fragment_config.xml index 0f298e44..4271e8d4 100644 --- a/app/src/main/res/layout/fragment_config.xml +++ b/app/src/main/res/layout/fragment_config.xml @@ -6,6 +6,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="@dimen/default_navigator_header_margin_top" + android:background="@color/black" tools:context=".view.ui.configuration.ConfigFragment"> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_MyAnimeList.png b/app/src/main/res/mipmap-hdpi/ic_MyAnimeList.png new file mode 100644 index 0000000000000000000000000000000000000000..ed0e638dccd699f63cd4e1020e8c595a82d6845e GIT binary patch literal 3474 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_MyAnimeList.png b/app/src/main/res/mipmap-xxhdpi/ic_MyAnimeList.png new file mode 100644 index 0000000000000000000000000000000000000000..df024b335d642264a66cee7d5ef2b7eaf0191c6b GIT binary patch literal 2932 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 5c8a1903..4a622736 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -9,6 +9,7 @@ Required App is not installed Up Down + Disconnect Access denied It not possible to obtain the access permissions to the informed folder, please obtain access in android settings. @@ -31,6 +32,9 @@ System Reader File link + Monitoring + Do you want to disconnect from %1$s\? + My Anime List Use page path to link pages? Consider double page by calculating dimensions? diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 4ea47d92..55f15223 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -9,6 +9,7 @@ O App necessário não está instalado Subir Descer + Desconectar Acesso negado Não foi possível obter a permissão de acesso a pasta informada, por favor libere o acesso na configuração do android. @@ -31,6 +32,9 @@ Sistema Leitor Arquivo vinculado + Monitoramento + Deseja desconectar do %1$s\? + My Anime List Utilizar o caminho da página para vincular as páginas? Considerar página dupla pelo calculo das dimensões? diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index df94f12c..cd8e879b 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -99,6 +99,9 @@ 20sp + 48dp + 10dp + 18sp 16sp 12sp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b26d4986..54c2081b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,6 +8,7 @@ Required App is not installed Up Down + Disconnect Access denied It not possible to obtain the access permissions to the informed folder, please obtain access in android settings. @@ -30,6 +31,9 @@ System Reader File link + Monitoring + Do you want to disconnect from %1$s\? + My Anime List Use page path to link pages? Consider double page by calculating dimensions? From fbdd3b4b3881c193204685911a800c9430fdebbf Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Sun, 24 Jul 2022 11:52:51 -0300 Subject: [PATCH 06/50] =?UTF-8?q?Corre=C3=A7=C3=A3o=20do=20nome=20dos=20ic?= =?UTF-8?q?ones.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/fragment_config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/fragment_config.xml b/app/src/main/res/layout/fragment_config.xml index 4271e8d4..39430e00 100644 --- a/app/src/main/res/layout/fragment_config.xml +++ b/app/src/main/res/layout/fragment_config.xml @@ -344,7 +344,7 @@ android:importantForAccessibility="no" android:padding="4dp" android:adjustViewBounds="true" - android:src="@mipmap/ic_MyAnimeList" /> + android:src="@mipmap/ic_myanimelist" /> Date: Sun, 24 Jul 2022 11:53:08 -0300 Subject: [PATCH 07/50] =?UTF-8?q?Corre=C3=A7=C3=A3o=20do=20nome=20dos=20ic?= =?UTF-8?q?ones.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ic_MyAnimeList.png => ic_myanimelist.png} | Bin .../{ic_MyAnimeList.png => ic_myanimelist.png} | Bin .../{ic_MyAnimeList.png => ic_myanimelist.png} | Bin .../{ic_MyAnimeList.png => ic_myanimelist.png} | Bin 4 files changed, 0 insertions(+), 0 deletions(-) rename app/src/main/res/mipmap-hdpi/{ic_MyAnimeList.png => ic_myanimelist.png} (100%) rename app/src/main/res/mipmap-mdpi/{ic_MyAnimeList.png => ic_myanimelist.png} (100%) rename app/src/main/res/mipmap-xxhdpi/{ic_MyAnimeList.png => ic_myanimelist.png} (100%) rename app/src/main/res/mipmap-xxxhdpi/{ic_MyAnimeList.png => ic_myanimelist.png} (100%) diff --git a/app/src/main/res/mipmap-hdpi/ic_MyAnimeList.png b/app/src/main/res/mipmap-hdpi/ic_myanimelist.png similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_MyAnimeList.png rename to app/src/main/res/mipmap-hdpi/ic_myanimelist.png diff --git a/app/src/main/res/mipmap-mdpi/ic_MyAnimeList.png b/app/src/main/res/mipmap-mdpi/ic_myanimelist.png similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_MyAnimeList.png rename to app/src/main/res/mipmap-mdpi/ic_myanimelist.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_MyAnimeList.png b/app/src/main/res/mipmap-xxhdpi/ic_myanimelist.png similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_MyAnimeList.png rename to app/src/main/res/mipmap-xxhdpi/ic_myanimelist.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_MyAnimeList.png b/app/src/main/res/mipmap-xxxhdpi/ic_myanimelist.png similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_MyAnimeList.png rename to app/src/main/res/mipmap-xxxhdpi/ic_myanimelist.png From 5acb8275ffa45de1ce64aa687e4bd6641b3e5b6c Mon Sep 17 00:00:00 2001 From: JhonnySalles Date: Fri, 29 Jul 2022 21:53:07 -0300 Subject: [PATCH 08/50] =?UTF-8?q?Corre=C3=A7=C3=B5es=20de=20erros.=20Ajust?= =?UTF-8?q?ado=20a=20cor=20dos=20bot=C3=B5es=20switch.=20Corrigido=20erro?= =?UTF-8?q?=20no=20nome=20do=20autor=20do=20MyAnimeList.=20Corrigido=20err?= =?UTF-8?q?o=20de=20crash=20ao=20entrar=20na=20pagina=20do=20vinculo=20vir?= =?UTF-8?q?ado.=20Corrigido=20erro=20de=20nome=20do=20manga=20quando=20vir?= =?UTF-8?q?ava=20na=20leitura.=20Ajustado=20degrade=20na=20imagem=20de=20f?= =?UTF-8?q?undo.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/entity/Information.kt | 2 +- .../tracker/mal/MyAnimeListMangaDetail.kt | 9 ++++++-- .../view/ui/pages_link/PagesLinkFragment.kt | 10 +++++---- .../view/ui/reader/ReaderActivity.kt | 4 +++- .../view/ui/window/FloatingSubtitleReader.kt | 2 ++ .../res/layout/activity_main_bar_menu.xml | 2 +- app/src/main/res/layout/fragment_config.xml | 4 ++-- .../res/layout/popup_reader_color_filter.xml | 20 +++++++++--------- .../layout/popup_subtitle_configuration.xml | 2 +- .../mipmap-xxxhdpi/main_header_cut_semi.png | Bin 0 -> 862472 bytes .../res/mipmap-xxxhdpi/main_header_semi.png | Bin 0 -> 928845 bytes app/src/main/res/values/styles.xml | 4 ++++ 12 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 app/src/main/res/mipmap-xxxhdpi/main_header_cut_semi.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/main_header_semi.png diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Information.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Information.kt index 8107f74b..473d5744 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Information.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/model/entity/Information.kt @@ -61,7 +61,7 @@ class Information( manga.endDate?.let { if (it.isNotEmpty()) this.endDate = MalTransform.getDate(it) } this.genres = manga.genres?.joinToString { it.name } ?: "" - this.authors = manga.authors?.joinToString { it.firstName + " " + it.lastName + "(" + it.role + ")" } ?: "" + this.authors = manga.authors?.joinToString { it.author.firstName + " " + it.author.lastName + "(" + it.role + ")" } ?: "" this.origin = MY_ANIME_LIST } } \ No newline at end of file diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaDetail.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaDetail.kt index 7851b781..6429e736 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaDetail.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/service/tracker/mal/MyAnimeListMangaDetail.kt @@ -76,14 +76,19 @@ data class MalGenres( ) data class MalAuthors( + @SerializedName("node") + val author: Author, + @SerializedName("role") + val role: String +) + +data class Author( @SerializedName("id") val id: Int, @SerializedName("first_name") val firstName: String, @SerializedName("last_name") val lastName: String, - @SerializedName("role") - val role: String ) data class MalStatus( diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkFragment.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkFragment.kt index 63b4b62b..4fe91e62 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkFragment.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/pages_link/PagesLinkFragment.kt @@ -139,10 +139,12 @@ class PagesLinkFragment : Fragment() { mMangaName = root.findViewById(R.id.pages_link_name_manga) mToolbar = requireActivity().findViewById(R.id.toolbar_manga_pages_link) - mExpandedButtonsGroupSize = mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams - mButtonsGroup.layoutParams = ConstraintLayout.LayoutParams(mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams) - mButtonsGroup.layoutParams.width = resources.getDimension(R.dimen.page_link_buttons_size).toInt() - mCollapseButtonsGroupSize = mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams + if (mHelp.tag.toString().compareTo("not_used", true) != 0) { + mExpandedButtonsGroupSize = mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams + mButtonsGroup.layoutParams = ConstraintLayout.LayoutParams(mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams) + mButtonsGroup.layoutParams.width = resources.getDimension(R.dimen.page_link_buttons_size).toInt() + mCollapseButtonsGroupSize = mButtonsGroup.layoutParams as ConstraintLayout.LayoutParams + } mScrollUp.visibility = View.GONE mScrollDown.visibility = View.GONE diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivity.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivity.kt index 2c500a21..61fc6012 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/reader/ReaderActivity.kt @@ -400,8 +400,10 @@ class ReaderActivity : AppCompatActivity(), OcrProcess { override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) val manga = (savedInstanceState.getSerializable(GeneralConsts.KEYS.OBJECT.MANGA) as Manga?) - if (manga != null) + if (manga != null) { mManga = manga + setTitles(manga.title, manga.bookMark.toString()) + } } private var mLastFloatingWindowOcr = false diff --git a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingSubtitleReader.kt b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingSubtitleReader.kt index d1cadf4f..22d705ca 100644 --- a/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingSubtitleReader.kt +++ b/app/src/main/java/br/com/fenix/bilingualmangareader/view/ui/window/FloatingSubtitleReader.kt @@ -272,6 +272,8 @@ class FloatingSubtitleReader constructor(private val context: Context, private v x = (mRealDisplaySize.x / 2) - (width / 2) y = context.resources.getDimension(R.dimen.floating_reader_initial_top_padding).toInt() } + + mOriginalHeight = mFloatingView.height } inner class ChangeTextTouchListener : GestureDetector.SimpleOnGestureListener() { diff --git a/app/src/main/res/layout/activity_main_bar_menu.xml b/app/src/main/res/layout/activity_main_bar_menu.xml index e8152553..1c5234c5 100644 --- a/app/src/main/res/layout/activity_main_bar_menu.xml +++ b/app/src/main/res/layout/activity_main_bar_menu.xml @@ -35,7 +35,7 @@ android:layout_gravity="top|center" android:contentDescription="@string/about_app_name" android:scaleType="centerCrop" - android:src="@mipmap/main_header_cut" /> + android:src="@mipmap/main_header_cut_semi" /> + android:theme="@style/SwitchMaterial" /> + android:theme="@style/SwitchMaterial" /> + app:layout_constraintTop_toTopOf="parent" /> @@ -199,8 +199,8 @@ android:paddingEnd="16dp" android:text="@string/popup_reading_blue_light" android:textColor="@color/text_primary" - app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_alpha" - app:thumbTint="@color/on_secondary" /> + android:theme="@style/SwitchMaterial" + app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_alpha" /> + android:theme="@style/SwitchMaterial" + app:layout_constraintTop_toBottomOf="@id/seekbar_blue_light_alpha" /> @@ -262,8 +262,8 @@ android:paddingEnd="16dp" android:text="@string/popup_reading_invert_color" android:textColor="@color/text_primary" - app:layout_constraintTop_toBottomOf="@id/switch_grayscale" - app:thumbTint="@color/on_secondary" /> + android:theme="@style/SwitchMaterial" + app:layout_constraintTop_toBottomOf="@id/switch_grayscale" /> + android:theme="@style/SwitchMaterial" + app:layout_constraintTop_toBottomOf="@id/switch_invert_color" /> diff --git a/app/src/main/res/layout/popup_subtitle_configuration.xml b/app/src/main/res/layout/popup_subtitle_configuration.xml index b1066bbf..109dd892 100644 --- a/app/src/main/res/layout/popup_subtitle_configuration.xml +++ b/app/src/main/res/layout/popup_subtitle_configuration.xml @@ -23,7 +23,7 @@ android:paddingEnd="16dp" android:text="@string/popup_reading_use_page_linked_in_search" android:textColor="@color/text_primary" - app:thumbTint="@color/on_secondary" /> + android:theme="@style/SwitchMaterial" /> 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