mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Feature/shikomori track (#1905)
* Add shikomori track * Fix char 'M' * Fix date in search
This commit is contained in:
		@@ -4,6 +4,7 @@ import android.content.Context
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.anilist.Anilist
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.kitsu.Kitsu
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.myanimelist.Myanimelist
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.shikomori.Shikomori
 | 
			
		||||
 | 
			
		||||
class TrackManager(private val context: Context) {
 | 
			
		||||
 | 
			
		||||
@@ -11,6 +12,7 @@ class TrackManager(private val context: Context) {
 | 
			
		||||
        const val MYANIMELIST = 1
 | 
			
		||||
        const val ANILIST = 2
 | 
			
		||||
        const val KITSU = 3
 | 
			
		||||
        const val SHIKOMORI = 4
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val myAnimeList = Myanimelist(context, MYANIMELIST)
 | 
			
		||||
@@ -19,7 +21,9 @@ class TrackManager(private val context: Context) {
 | 
			
		||||
 | 
			
		||||
    val kitsu = Kitsu(context, KITSU)
 | 
			
		||||
 | 
			
		||||
    val services = listOf(myAnimeList, aniList, kitsu)
 | 
			
		||||
    val shikomori = Shikomori(context, SHIKOMORI)
 | 
			
		||||
 | 
			
		||||
    val services = listOf(myAnimeList, aniList, kitsu, shikomori)
 | 
			
		||||
 | 
			
		||||
    fun getService(id: Int) = services.find { it.id == id }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,13 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.track.shikomori
 | 
			
		||||
 | 
			
		||||
data class OAuth(
 | 
			
		||||
        val access_token: String,
 | 
			
		||||
        val token_type: String,
 | 
			
		||||
        val created_at: Long,
 | 
			
		||||
        val expires_in: Long,
 | 
			
		||||
        val refresh_token: String?) {
 | 
			
		||||
 | 
			
		||||
    // Access token lives 1 day
 | 
			
		||||
    fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,138 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.track.shikomori
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.graphics.Color
 | 
			
		||||
import com.google.gson.Gson
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Track
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackService
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
 | 
			
		||||
import rx.Completable
 | 
			
		||||
import rx.Observable
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
 | 
			
		||||
class Shikomori(private val context: Context, id: Int) : TrackService(id) {
 | 
			
		||||
 | 
			
		||||
    override fun getScoreList(): List<String> {
 | 
			
		||||
        return IntRange(0, 10).map(Int::toString)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun displayScore(track: Track): String {
 | 
			
		||||
        return track.score.toInt().toString()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun add(track: Track): Observable<Track> {
 | 
			
		||||
        return api.addLibManga(track, getUsername())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun update(track: Track): Observable<Track> {
 | 
			
		||||
        if (track.total_chapters != 0 && track.last_chapter_read == track.total_chapters) {
 | 
			
		||||
            track.status = COMPLETED
 | 
			
		||||
        }
 | 
			
		||||
        return api.updateLibManga(track, getUsername())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun bind(track: Track): Observable<Track> {
 | 
			
		||||
        return api.findLibManga(track, getUsername())
 | 
			
		||||
                .flatMap { remoteTrack ->
 | 
			
		||||
                    if (remoteTrack != null) {
 | 
			
		||||
                        track.copyPersonalFrom(remoteTrack)
 | 
			
		||||
                        track.library_id = remoteTrack.library_id
 | 
			
		||||
                        update(track)
 | 
			
		||||
                    } else {
 | 
			
		||||
                        // Set default fields if it's not found in the list
 | 
			
		||||
                        track.score = DEFAULT_SCORE.toFloat()
 | 
			
		||||
                        track.status = DEFAULT_STATUS
 | 
			
		||||
                        add(track)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun search(query: String): Observable<List<TrackSearch>> {
 | 
			
		||||
        return api.search(query)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun refresh(track: Track): Observable<Track> {
 | 
			
		||||
        return api.findLibManga(track, getUsername())
 | 
			
		||||
                .map { remoteTrack ->
 | 
			
		||||
                    if (remoteTrack != null) {
 | 
			
		||||
                        track.copyPersonalFrom(remoteTrack)
 | 
			
		||||
                        track.total_chapters = remoteTrack.total_chapters
 | 
			
		||||
                    }
 | 
			
		||||
                    track
 | 
			
		||||
                }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val READING = 1
 | 
			
		||||
        const val COMPLETED = 2
 | 
			
		||||
        const val ON_HOLD = 3
 | 
			
		||||
        const val DROPPED = 4
 | 
			
		||||
        const val PLANNING = 5
 | 
			
		||||
        const val REPEATING = 6
 | 
			
		||||
 | 
			
		||||
        const val DEFAULT_STATUS = READING
 | 
			
		||||
        const val DEFAULT_SCORE = 0
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override val name = "Shikomori"
 | 
			
		||||
 | 
			
		||||
    private val gson: Gson by injectLazy()
 | 
			
		||||
 | 
			
		||||
    private val interceptor by lazy { ShikomoriInterceptor(this, gson) }
 | 
			
		||||
 | 
			
		||||
    private val api by lazy { ShikomoriApi(client, interceptor) }
 | 
			
		||||
 | 
			
		||||
    override fun getLogo() = R.drawable.shikomori
 | 
			
		||||
 | 
			
		||||
    override fun getLogoColor() = Color.rgb(40, 40, 40)
 | 
			
		||||
 | 
			
		||||
    override fun getStatusList(): List<Int> {
 | 
			
		||||
        return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLANNING, REPEATING)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getStatus(status: Int): String = with(context) {
 | 
			
		||||
        when (status) {
 | 
			
		||||
            READING -> getString(R.string.reading)
 | 
			
		||||
            COMPLETED -> getString(R.string.completed)
 | 
			
		||||
            ON_HOLD -> getString(R.string.on_hold)
 | 
			
		||||
            DROPPED -> getString(R.string.dropped)
 | 
			
		||||
            PLANNING -> getString(R.string.plan_to_read)
 | 
			
		||||
            REPEATING -> getString(R.string.repeating)
 | 
			
		||||
            else -> ""
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun login(username: String, password: String) = login(password)
 | 
			
		||||
 | 
			
		||||
    fun login(code: String): Completable {
 | 
			
		||||
        return api.accessToken(code).map { oauth: OAuth? ->
 | 
			
		||||
            interceptor.newAuth(oauth)
 | 
			
		||||
            if (oauth != null) {
 | 
			
		||||
                val user = api.getCurrentUser()
 | 
			
		||||
                saveCredentials(user.toString(), oauth.access_token)
 | 
			
		||||
            }
 | 
			
		||||
        }.doOnError {
 | 
			
		||||
            logout()
 | 
			
		||||
        }.toCompletable()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun saveToken(oauth: OAuth?) {
 | 
			
		||||
        val json = gson.toJson(oauth)
 | 
			
		||||
        preferences.trackToken(this).set(json)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun restoreToken(): OAuth? {
 | 
			
		||||
        return try {
 | 
			
		||||
            gson.fromJson(preferences.trackToken(this).get(), OAuth::class.java)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            null
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun logout() {
 | 
			
		||||
        super.logout()
 | 
			
		||||
        preferences.trackToken(this).set(null)
 | 
			
		||||
        interceptor.newAuth(null)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,189 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.track.shikomori
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import com.github.salomonbrys.kotson.array
 | 
			
		||||
import com.github.salomonbrys.kotson.jsonObject
 | 
			
		||||
import com.github.salomonbrys.kotson.nullString
 | 
			
		||||
import com.github.salomonbrys.kotson.obj
 | 
			
		||||
import com.google.gson.Gson
 | 
			
		||||
import com.google.gson.JsonObject
 | 
			
		||||
import com.google.gson.JsonParser
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Track
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
 | 
			
		||||
import eu.kanade.tachiyomi.network.GET
 | 
			
		||||
import eu.kanade.tachiyomi.network.POST
 | 
			
		||||
import eu.kanade.tachiyomi.network.asObservableSuccess
 | 
			
		||||
import okhttp3.*
 | 
			
		||||
import rx.Observable
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
 | 
			
		||||
class ShikomoriApi(private val client: OkHttpClient, interceptor: ShikomoriInterceptor) {
 | 
			
		||||
 | 
			
		||||
    private val gson: Gson by injectLazy()
 | 
			
		||||
    private val parser = JsonParser()
 | 
			
		||||
    private val jsonime = MediaType.parse("application/json; charset=utf-8")
 | 
			
		||||
    private val authClient = client.newBuilder().addInterceptor(interceptor).build()
 | 
			
		||||
 | 
			
		||||
    fun addLibManga(track: Track, user_id: String): Observable<Track> {
 | 
			
		||||
        val payload = jsonObject(
 | 
			
		||||
                "user_rate" to jsonObject(
 | 
			
		||||
                        "user_id" to user_id,
 | 
			
		||||
                        "target_id" to track.media_id,
 | 
			
		||||
                        "target_type" to "Manga",
 | 
			
		||||
                        "chapters" to track.last_chapter_read,
 | 
			
		||||
                        "score" to track.score.toInt(),
 | 
			
		||||
                        "status" to track.toShikomoriStatus()
 | 
			
		||||
                )
 | 
			
		||||
        )
 | 
			
		||||
        val body = RequestBody.create(jsonime, payload.toString())
 | 
			
		||||
        val request = Request.Builder()
 | 
			
		||||
                .url("$apiUrl/v2/user_rates")
 | 
			
		||||
                .post(body)
 | 
			
		||||
                .build()
 | 
			
		||||
        return authClient.newCall(request)
 | 
			
		||||
                .asObservableSuccess()
 | 
			
		||||
                .map {
 | 
			
		||||
                    track
 | 
			
		||||
                }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun updateLibManga(track: Track, user_id: String): Observable<Track> = addLibManga(track, user_id)
 | 
			
		||||
 | 
			
		||||
    fun search(search: String): Observable<List<TrackSearch>> {
 | 
			
		||||
        val url = Uri.parse("$apiUrl/mangas").buildUpon()
 | 
			
		||||
                .appendQueryParameter("order", "popularity")
 | 
			
		||||
                .appendQueryParameter("search", search)
 | 
			
		||||
                .appendQueryParameter("limit", "20")
 | 
			
		||||
                .build()
 | 
			
		||||
        val request = Request.Builder()
 | 
			
		||||
                .url(url.toString())
 | 
			
		||||
                .get()
 | 
			
		||||
                .build()
 | 
			
		||||
        return authClient.newCall(request)
 | 
			
		||||
                .asObservableSuccess()
 | 
			
		||||
                .map { netResponse ->
 | 
			
		||||
                    val responseBody = netResponse.body()?.string().orEmpty()
 | 
			
		||||
                    if (responseBody.isEmpty()) {
 | 
			
		||||
                        throw Exception("Null Response")
 | 
			
		||||
                    }
 | 
			
		||||
                    val response = parser.parse(responseBody).array
 | 
			
		||||
                    response.map { jsonToSearch(it.obj) }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun jsonToSearch(obj: JsonObject): TrackSearch {
 | 
			
		||||
        return TrackSearch.create(TrackManager.SHIKOMORI).apply {
 | 
			
		||||
            media_id = obj["id"].asInt
 | 
			
		||||
            title = obj["name"].asString
 | 
			
		||||
            total_chapters = obj["chapters"].asInt
 | 
			
		||||
            cover_url = baseUrl + obj["image"].obj["preview"].asString
 | 
			
		||||
            summary = ""
 | 
			
		||||
            tracking_url = baseUrl + obj["url"].asString
 | 
			
		||||
            publishing_status = obj["status"].asString
 | 
			
		||||
            publishing_type = obj["kind"].asString
 | 
			
		||||
            start_date = obj.get("aired_on").nullString.orEmpty()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun jsonToTrack(obj: JsonObject): Track {
 | 
			
		||||
        return Track.create(TrackManager.SHIKOMORI).apply {
 | 
			
		||||
            media_id = obj["id"].asInt
 | 
			
		||||
            title = ""
 | 
			
		||||
            last_chapter_read = obj["chapters"].asInt
 | 
			
		||||
            total_chapters = obj["chapters"].asInt
 | 
			
		||||
            score = (obj["score"].asInt).toFloat()
 | 
			
		||||
            status = toTrackStatus(obj["status"].asString)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun findLibManga(track: Track, user_id: String): Observable<Track?> {
 | 
			
		||||
        val url = Uri.parse("$apiUrl/v2/user_rates").buildUpon()
 | 
			
		||||
                .appendQueryParameter("user_id", user_id)
 | 
			
		||||
                .appendQueryParameter("target_id", track.media_id.toString())
 | 
			
		||||
                .appendQueryParameter("target_type", "Manga")
 | 
			
		||||
                .build()
 | 
			
		||||
        val request = Request.Builder()
 | 
			
		||||
                .url(url.toString())
 | 
			
		||||
                .get()
 | 
			
		||||
                .build()
 | 
			
		||||
        return authClient.newCall(request)
 | 
			
		||||
                .asObservableSuccess()
 | 
			
		||||
                .map { netResponse ->
 | 
			
		||||
                    val responseBody = netResponse.body()?.string().orEmpty()
 | 
			
		||||
                    if (responseBody.isEmpty()) {
 | 
			
		||||
                        throw Exception("Null Response")
 | 
			
		||||
                    }
 | 
			
		||||
                    val response = parser.parse(responseBody).array
 | 
			
		||||
                    if (response.size() > 1) {
 | 
			
		||||
                        throw Exception("Too much mangas in response")
 | 
			
		||||
                    }
 | 
			
		||||
                    val entry = response.map {
 | 
			
		||||
                        jsonToTrack(it.obj)
 | 
			
		||||
                    }
 | 
			
		||||
                    entry.firstOrNull()
 | 
			
		||||
                }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getCurrentUser(): Int {
 | 
			
		||||
        val user = authClient.newCall(GET("$apiUrl/users/whoami")).execute().body()?.string()
 | 
			
		||||
        return parser.parse(user).obj["id"].asInt
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun accessToken(code: String): Observable<OAuth> {
 | 
			
		||||
        return client.newCall(accessTokenRequest(code)).asObservableSuccess().map { netResponse ->
 | 
			
		||||
            val responseBody = netResponse.body()?.string().orEmpty()
 | 
			
		||||
            if (responseBody.isEmpty()) {
 | 
			
		||||
                throw Exception("Null Response")
 | 
			
		||||
            }
 | 
			
		||||
            gson.fromJson(responseBody, OAuth::class.java)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun accessTokenRequest(code: String) = POST(oauthUrl,
 | 
			
		||||
            body = FormBody.Builder()
 | 
			
		||||
                    .add("grant_type", "authorization_code")
 | 
			
		||||
                    .add("client_id", clientId)
 | 
			
		||||
                    .add("client_secret", clientSecret)
 | 
			
		||||
                    .add("code", code)
 | 
			
		||||
                    .add("redirect_uri", redirectUrl)
 | 
			
		||||
                    .build()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private const val clientId = "1aaf4cf232372708e98b5abc813d795b539c5a916dbbfe9ac61bf02a360832cc"
 | 
			
		||||
        private const val clientSecret = "229942c742dd4cde803125d17d64501d91c0b12e14cb1e5120184d77d67024c0"
 | 
			
		||||
 | 
			
		||||
        private const val baseUrl = "https://shikimori.org"
 | 
			
		||||
        private const val apiUrl = "https://shikimori.org/api"
 | 
			
		||||
        private const val oauthUrl = "https://shikimori.org/oauth/token"
 | 
			
		||||
        private const val loginUrl = "https://shikimori.org/oauth/authorize"
 | 
			
		||||
 | 
			
		||||
        private const val redirectUrl = "tachiyomi://shikimori-auth"
 | 
			
		||||
        private const val baseMangaUrl = "$apiUrl/mangas"
 | 
			
		||||
 | 
			
		||||
        fun mangaUrl(remoteId: Int): String {
 | 
			
		||||
            return "$baseMangaUrl/$remoteId"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun authUrl() =
 | 
			
		||||
                Uri.parse(loginUrl).buildUpon()
 | 
			
		||||
                        .appendQueryParameter("client_id", clientId)
 | 
			
		||||
                        .appendQueryParameter("redirect_uri", redirectUrl)
 | 
			
		||||
                        .appendQueryParameter("response_type", "code")
 | 
			
		||||
                        .build()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        fun refreshTokenRequest(token: String) = POST(oauthUrl,
 | 
			
		||||
                body = FormBody.Builder()
 | 
			
		||||
                        .add("grant_type", "refresh_token")
 | 
			
		||||
                        .add("client_id", clientId)
 | 
			
		||||
                        .add("client_secret", clientSecret)
 | 
			
		||||
                        .add("refresh_token", token)
 | 
			
		||||
                        .build())
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,43 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.track.shikomori
 | 
			
		||||
 | 
			
		||||
import com.google.gson.Gson
 | 
			
		||||
import okhttp3.Interceptor
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
 | 
			
		||||
class ShikomoriInterceptor(val shikomori: Shikomori, val gson: Gson) : Interceptor {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * OAuth object used for authenticated requests.
 | 
			
		||||
     */
 | 
			
		||||
    private var oauth: OAuth? = shikomori.restoreToken()
 | 
			
		||||
 | 
			
		||||
    override fun intercept(chain: Interceptor.Chain): Response {
 | 
			
		||||
        val originalRequest = chain.request()
 | 
			
		||||
 | 
			
		||||
        val currAuth = oauth ?: throw Exception("Not authenticated with Shikomori")
 | 
			
		||||
 | 
			
		||||
        val refreshToken = currAuth.refresh_token!!
 | 
			
		||||
 | 
			
		||||
        // Refresh access token if expired.
 | 
			
		||||
        if (currAuth.isExpired()) {
 | 
			
		||||
            val response = chain.proceed(ShikomoriApi.refreshTokenRequest(refreshToken))
 | 
			
		||||
            if (response.isSuccessful) {
 | 
			
		||||
                newAuth(gson.fromJson(response.body()!!.string(), OAuth::class.java))
 | 
			
		||||
            } else {
 | 
			
		||||
                response.close()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Add the authorization header to the original request.
 | 
			
		||||
        val authRequest = originalRequest.newBuilder()
 | 
			
		||||
                .addHeader("Authorization", "Bearer ${oauth!!.access_token}")
 | 
			
		||||
                .header("User-Agent", "Tachiyomi")
 | 
			
		||||
                .build()
 | 
			
		||||
 | 
			
		||||
        return chain.proceed(authRequest)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun newAuth(oauth: OAuth?) {
 | 
			
		||||
        this.oauth = oauth
 | 
			
		||||
        shikomori.saveToken(oauth)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.track.shikomori
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Track
 | 
			
		||||
 | 
			
		||||
fun Track.toShikomoriStatus() = when (status) {
 | 
			
		||||
    Shikomori.READING -> "watching"
 | 
			
		||||
    Shikomori.COMPLETED -> "completed"
 | 
			
		||||
    Shikomori.ON_HOLD -> "on_hold"
 | 
			
		||||
    Shikomori.DROPPED -> "dropped"
 | 
			
		||||
    Shikomori.PLANNING -> "planned"
 | 
			
		||||
    Shikomori.REPEATING -> "rewatching"
 | 
			
		||||
    else -> throw NotImplementedError("Unknown status")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun toTrackStatus(status: String) = when (status) {
 | 
			
		||||
    "watching" -> Shikomori.READING
 | 
			
		||||
    "completed" -> Shikomori.COMPLETED
 | 
			
		||||
    "on_hold" -> Shikomori.ON_HOLD
 | 
			
		||||
    "dropped" -> Shikomori.DROPPED
 | 
			
		||||
    "planned" -> Shikomori.PLANNING
 | 
			
		||||
    "rewatching" -> Shikomori.REPEATING
 | 
			
		||||
 | 
			
		||||
    else -> throw Exception("Unknown status")
 | 
			
		||||
}
 | 
			
		||||
@@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackService
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.anilist.AnilistApi
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.shikomori.ShikomoriApi
 | 
			
		||||
import eu.kanade.tachiyomi.util.getResourceColor
 | 
			
		||||
import eu.kanade.tachiyomi.widget.preference.LoginPreference
 | 
			
		||||
import eu.kanade.tachiyomi.widget.preference.TrackLoginDialog
 | 
			
		||||
@@ -53,6 +54,15 @@ class SettingsTrackingController : SettingsController(),
 | 
			
		||||
                    dialog.showDialog(router)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            trackPreference(trackManager.shikomori) {
 | 
			
		||||
                onClick {
 | 
			
		||||
                    val tabsIntent = CustomTabsIntent.Builder()
 | 
			
		||||
                            .setToolbarColor(context.getResourceColor(R.attr.colorPrimary))
 | 
			
		||||
                            .build()
 | 
			
		||||
                    tabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
 | 
			
		||||
                    tabsIntent.launchUrl(activity, ShikomoriApi.authUrl())
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -70,6 +80,7 @@ class SettingsTrackingController : SettingsController(),
 | 
			
		||||
        super.onActivityResumed(activity)
 | 
			
		||||
        // Manually refresh anilist holder
 | 
			
		||||
        updatePreference(trackManager.aniList.id)
 | 
			
		||||
        updatePreference(trackManager.shikomori.id)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun updatePreference(id: Int) {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.setting
 | 
			
		||||
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.support.v7.app.AppCompatActivity
 | 
			
		||||
import android.view.Gravity.CENTER
 | 
			
		||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 | 
			
		||||
import android.widget.FrameLayout
 | 
			
		||||
import android.widget.ProgressBar
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
import eu.kanade.tachiyomi.ui.main.MainActivity
 | 
			
		||||
import rx.android.schedulers.AndroidSchedulers
 | 
			
		||||
import rx.schedulers.Schedulers
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
 | 
			
		||||
class ShikomoriLoginActivity : AppCompatActivity() {
 | 
			
		||||
 | 
			
		||||
    private val trackManager: TrackManager by injectLazy()
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedState)
 | 
			
		||||
 | 
			
		||||
        val view = ProgressBar(this)
 | 
			
		||||
        setContentView(view, FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, CENTER))
 | 
			
		||||
 | 
			
		||||
        val code = intent.data?.getQueryParameter("code")
 | 
			
		||||
        if (code != null) {
 | 
			
		||||
            trackManager.shikomori.login(code)
 | 
			
		||||
                    .subscribeOn(Schedulers.io())
 | 
			
		||||
                    .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                    .subscribe({
 | 
			
		||||
                        returnToSettings()
 | 
			
		||||
                    }, {
 | 
			
		||||
                        returnToSettings()
 | 
			
		||||
                    })
 | 
			
		||||
        } else {
 | 
			
		||||
            trackManager.shikomori.logout()
 | 
			
		||||
            returnToSettings()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun returnToSettings() {
 | 
			
		||||
        finish()
 | 
			
		||||
 | 
			
		||||
        val intent = Intent(this, MainActivity::class.java)
 | 
			
		||||
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
 | 
			
		||||
        startActivity(intent)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user