Compare commits

..

28 Commits

Author SHA1 Message Date
f8a03226ee Release v0.7.3 2018-04-28 11:10:29 +02:00
32db1e3045 Run downloader in foreground service 2018-04-28 10:54:27 +02:00
303e6c0102 Reorganize reader settings. Update Conductor version 2018-04-28 10:40:08 +02:00
18883f1ba3 Crop borders for webtoon now have a separate setting. Close #972 2018-04-27 16:55:12 +02:00
5c31271e91 Workaround a crash related to saving instance state and child controllers 2018-04-25 16:26:46 +02:00
00981cf4e8 Include firebase analytics 2018-04-25 13:46:57 +02:00
968f4a69e8 Separate 'en' locale into 'en-US' and 'en-GB' for displaying dates 2018-04-22 13:15:47 +02:00
e7e1a9bf50 Fix #1073 2018-04-15 13:26:33 +02:00
fe1becb001 Update strings.xml (#1324) 2018-04-15 12:59:52 +02:00
7789171c71 Remove F-Droid.org link (#1357)
* remove fdroid.org

* Update README.md

* fix broken links
2018-04-15 12:48:03 +02:00
3fd2222c99 Update russian sources (#1362)
1) moved headerBuilder to imageRequest
2) changed the method of gets thumbnails
3) updated js for genres
4) update genre list
2018-04-15 12:47:39 +02:00
6de36a88c0 Fix tracking search layout 2018-04-13 16:28:09 +02:00
b37685542d Add new translation link (#1355) 2018-04-09 16:25:30 +02:00
a2b1b9e746 Release v0.7.2 2018-04-08 19:10:18 +02:00
8017324033 Fix #1351 2018-04-08 18:58:28 +02:00
7464497c88 Use our OkHttpClient in updates checker. It should fix the updater on KitKat due to TLS 2018-04-06 10:02:01 +02:00
499def3daa Fix downloaded text drawn outside the screen 2018-04-06 08:29:17 +02:00
6931b75cc5 Release v0.7.1 2018-04-05 23:01:32 +02:00
f853610578 Show last update if date > 0 2018-04-05 22:55:23 +02:00
69f51b88bf Fix typo in layout 2018-04-05 22:08:23 +02:00
e0d680201a Update constraint layout & fix broken layouts 2018-04-05 21:50:44 +02:00
1566b8f8b8 Provide accept & accept-language to cloudflare 2018-04-05 19:12:17 +02:00
4bbf78e840 Don't send cache control with cloudflare challenge 2018-04-05 11:58:28 +02:00
7ab16a69df Update travis script 2018-04-05 10:56:16 +02:00
95e60ed775 Update cloudflare interceptor and android studio 2018-04-05 10:36:29 +02:00
d38cd2547a Enable TLS 1.1 and TLS 1.2 on Android KitKat (and older) (#1316)
* Enable TLS 1.1 and TLS 1.2 on Android KitKat (and older)

* enable SSLv3

* use extension function
2018-03-25 17:08:29 +02:00
2159b72e69 Dialog color fix (#1308) 2018-03-14 18:01:30 +01:00
81c23bbf9d Update Batoto toString() method to support downloaded chapters 2018-03-14 12:54:31 +01:00
43 changed files with 480 additions and 182 deletions

View File

@ -1,7 +1,7 @@
language: android language: android
android: android:
components: components:
- build-tools-27.0.2 - build-tools-27.0.3
- android-27 - android-27
- extra-android-m2repository - extra-android-m2repository
- extra-google-m2repository - extra-google-m2repository

View File

@ -2,6 +2,8 @@
git fetch --unshallow #required for commit count git fetch --unshallow #required for commit count
cp .travis/google-services.json app/
if [ -z "$TRAVIS_TAG" ]; then if [ -z "$TRAVIS_TAG" ]; then
./gradlew clean assembleStandardDebug ./gradlew clean assembleStandardDebug

View File

@ -0,0 +1,73 @@
{
"project_info": {
"project_number": "777921915939",
"firebase_url": "https://tachiyomi-47364.firebaseio.com",
"project_id": "tachiyomi-47364",
"storage_bucket": "tachiyomi-47364.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:777921915939:android:36544cd2d96c50c7",
"android_client_info": {
"package_name": "eu.kanade.tachiyomi"
}
},
"oauth_client": [
{
"client_id": "777921915939-9q25jvgbdtpk91daqlk7sa1cbdcg77o6.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAHr8RxyeiSPC_MxJTnivz-hmdo5oX0QQQ"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:777921915939:android:564fdc1d62efd1de",
"android_client_info": {
"package_name": "eu.kanade.tachiyomi.debug"
}
},
"oauth_client": [
{
"client_id": "777921915939-9q25jvgbdtpk91daqlk7sa1cbdcg77o6.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAHr8RxyeiSPC_MxJTnivz-hmdo5oX0QQQ"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}

View File

@ -1,6 +1,6 @@
| Build | Download | F-Droid | Contribute | Contact | | Build | Stable | Dev | Contribute | Contact |
|-------|----------|---------|------------|---------| |-------|----------|---------|------------|---------|
| [![Travis](https://img.shields.io/travis/inorichi/tachiyomi.svg)](https://travis-ci.org/inorichi/tachiyomi) | [![stable release](https://img.shields.io/github/release/inorichi/tachiyomi.svg?maxAge=3600&label=stable)](https://github.com/inorichi/tachiyomi/releases) [![latest dev build](https://img.shields.io/badge/dev-latest%20build-blue.svg)](http://tachiyomi.kanade.eu/latest) | [![fdroid release](https://img.shields.io/badge/stable-f--droid.org-blue.svg)](https://f-droid.org/repository/browse/?fdid=eu.kanade.tachiyomi) [![fdroid dev](https://img.shields.io/badge/dev-wiki-blue.svg)](//github.com/inorichi/tachiyomi/wiki/FDroid-for-dev-versions) | [![Translation status](http://weblate.j2ghz.com/widgets/tachiyomi/-/svg-badge.svg)](https://github.com/inorichi/tachiyomi/wiki/Translation) | [![Discord](https://img.shields.io/discord/349436576037732353.svg)](https://discord.gg/2dDQBv2) | | [![Travis](https://img.shields.io/travis/inorichi/tachiyomi.svg)](https://travis-ci.org/inorichi/tachiyomi) | [![stable release](https://img.shields.io/github/release/inorichi/tachiyomi.svg?maxAge=3600&label=download%20(autoupdate%20included))](https://github.com/inorichi/tachiyomi/releases) | [![latest dev build](https://img.shields.io/badge/download-latest%20build-blue.svg)](http://tachiyomi.kanade.eu/latest) [![fdroid dev](https://img.shields.io/badge/autoupdate-wiki-blue.svg)](//github.com/inorichi/tachiyomi/wiki/F-Droid-for-dev-versions) | [![Translation status](https://hosted.weblate.org/widgets/tachiyomi/-/svg-badge.svg)](https://hosted.weblate.org/engage/tachiyomi/?utm_source=widget) | [![Discord](https://img.shields.io/discord/349436576037732353.svg)](https://discord.gg/2dDQBv2) |
# ![app icon](./.github/readme-images/app-icon.png)Tachiyomi # ![app icon](./.github/readme-images/app-icon.png)Tachiyomi
@ -21,9 +21,9 @@ Features include:
* Create backups locally or to your cloud service of choice * Create backups locally or to your cloud service of choice
## Download ## Download
Get the app from our [releases page](https://github.com/inorichi/tachiyomi/releases) or from [f-droid](https://f-droid.org/packages/eu.kanade.tachiyomi/). Get the app from our [releases page](https://github.com/inorichi/tachiyomi/releases).
If you want to try new features before they get to the stable release, you can download the dev version [here](http://tachiyomi.kanade.eu/latest) (auto-updates not included), or add our [F-Droid repo](https://github.com/inorichi/tachiyomi/wiki/FDroid-for-dev-versions). If you want to try new features before they get to the stable release, you can download the dev version [here](http://tachiyomi.kanade.eu/latest) (auto-updates not included), or add our [F-Droid repo](https://github.com/inorichi/tachiyomi/wiki/F-Droid-for-dev-versions).
## Issues, Feature Requests and Contributing ## Issues, Feature Requests and Contributing

1
app/.gitignore vendored
View File

@ -2,3 +2,4 @@
*iml *iml
*.iml *.iml
custom.gradle custom.gradle
google-services.json

View File

@ -30,7 +30,7 @@ ext {
android { android {
compileSdkVersion 27 compileSdkVersion 27
buildToolsVersion "27.0.2" buildToolsVersion '27.0.3'
publishNonDefault true publishNonDefault true
defaultConfig { defaultConfig {
@ -38,8 +38,8 @@ android {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 27 targetSdkVersion 27
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
versionCode 33 versionCode 36
versionName "0.7.0" versionName "0.7.3"
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\"" buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""
@ -116,10 +116,12 @@ dependencies {
implementation "com.android.support:support-annotations:$support_library_version" implementation "com.android.support:support-annotations:$support_library_version"
implementation "com.android.support:customtabs:$support_library_version" implementation "com.android.support:customtabs:$support_library_version"
implementation 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta6'
implementation 'com.android.support:multidex:1.0.2' implementation 'com.android.support:multidex:1.0.2'
standardImplementation 'com.google.firebase:firebase-core:12.0.1'
// ReactiveX // ReactiveX
implementation 'io.reactivex:rxandroid:1.2.1' implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.3.6' implementation 'io.reactivex:rxjava:1.3.6'
@ -153,7 +155,7 @@ dependencies {
// Job scheduling // Job scheduling
implementation 'com.evernote:android-job:1.2.4' implementation 'com.evernote:android-job:1.2.4'
implementation 'com.google.android.gms:play-services-gcm:11.8.0' implementation 'com.google.android.gms:play-services-gcm:12.0.1'
// Changelog // Changelog
implementation 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0' implementation 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0'
@ -201,7 +203,7 @@ dependencies {
implementation 'me.gujun.android.taggroup:library:1.4@aar' implementation 'me.gujun.android.taggroup:library:1.4@aar'
// Conductor // Conductor
implementation "com.github.inorichi.Conductor:conductor:05c4d4d" implementation "com.github.inorichi.Conductor:conductor:be8b3c5"
implementation ("com.bluelinelabs:conductor-support:2.1.5-SNAPSHOT") { implementation ("com.bluelinelabs:conductor-support:2.1.5-SNAPSHOT") {
exclude group: "com.bluelinelabs", module: "conductor" exclude group: "com.bluelinelabs", module: "conductor"
} }
@ -254,3 +256,7 @@ kotlin {
androidExtensions { androidExtensions {
experimental = true experimental = true
} }
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Standard")) {
apply plugin: 'com.google.gms.google-services'
}

View File

@ -1,16 +1,20 @@
package eu.kanade.tachiyomi.data.download package eu.kanade.tachiyomi.data.download
import android.app.Notification
import android.app.Service import android.app.Service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.NetworkInfo.State.CONNECTED import android.net.NetworkInfo.State.CONNECTED
import android.net.NetworkInfo.State.DISCONNECTED import android.net.NetworkInfo.State.DISCONNECTED
import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.os.PowerManager import android.os.PowerManager
import android.support.v4.app.NotificationCompat
import com.github.pwittchen.reactivenetwork.library.Connectivity import com.github.pwittchen.reactivenetwork.library.Connectivity
import com.github.pwittchen.reactivenetwork.library.ReactiveNetwork import com.github.pwittchen.reactivenetwork.library.ReactiveNetwork
import com.jakewharton.rxrelay.BehaviorRelay import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.util.connectivityManager import eu.kanade.tachiyomi.util.connectivityManager
import eu.kanade.tachiyomi.util.plusAssign import eu.kanade.tachiyomi.util.plusAssign
@ -41,7 +45,12 @@ class DownloadService : Service() {
* @param context the application context. * @param context the application context.
*/ */
fun start(context: Context) { fun start(context: Context) {
context.startService(Intent(context, DownloadService::class.java)) val intent = Intent(context, DownloadService::class.java)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
context.startService(intent)
} else {
context.startForegroundService(intent)
}
} }
/** /**
@ -81,6 +90,7 @@ class DownloadService : Service() {
*/ */
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
startForeground(Notifications.ID_DOWNLOAD_CHAPTER, getPlaceholderNotification())
runningRelay.call(true) runningRelay.call(true)
subscriptions = CompositeSubscription() subscriptions = CompositeSubscription()
listenDownloaderState() listenDownloaderState()
@ -176,4 +186,10 @@ class DownloadService : Service() {
if (!isHeld) acquire() if (!isHeld) acquire()
} }
private fun getPlaceholderNotification(): Notification {
return NotificationCompat.Builder(this, Notifications.CHANNEL_DOWNLOADER)
.setContentTitle(getString(R.string.download_notifier_downloader_title))
.build()
}
} }

View File

@ -39,6 +39,8 @@ object PreferenceKeys {
const val cropBorders = "crop_borders" const val cropBorders = "crop_borders"
const val cropBordersWebtoon = "crop_borders_webtoon"
const val readWithTapping = "reader_tap" const val readWithTapping = "reader_tap"
const val readWithVolumeKeys = "reader_volume_keys" const val readWithVolumeKeys = "reader_volume_keys"

View File

@ -67,6 +67,8 @@ class PreferencesHelper(val context: Context) {
fun cropBorders() = rxPrefs.getBoolean(Keys.cropBorders, false) fun cropBorders() = rxPrefs.getBoolean(Keys.cropBorders, false)
fun cropBordersWebtoon() = rxPrefs.getBoolean(Keys.cropBordersWebtoon, false)
fun readWithTapping() = rxPrefs.getBoolean(Keys.readWithTapping, true) fun readWithTapping() = rxPrefs.getBoolean(Keys.readWithTapping, true)
fun readWithVolumeKeys() = rxPrefs.getBoolean(Keys.readWithVolumeKeys, false) fun readWithVolumeKeys() = rxPrefs.getBoolean(Keys.readWithVolumeKeys, false)

View File

@ -1,10 +1,13 @@
package eu.kanade.tachiyomi.data.updater package eu.kanade.tachiyomi.data.updater
import eu.kanade.tachiyomi.network.NetworkHelper
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET import retrofit2.http.GET
import rx.Observable import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
/** /**
* Used to connect with the Github API. * Used to connect with the Github API.
@ -17,6 +20,7 @@ interface GithubService {
.baseUrl("https://api.github.com") .baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(Injekt.get<NetworkHelper>().client)
.build() .build()
return restAdapter.create(GithubService::class.java) return restAdapter.create(GithubService::class.java)

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.network package eu.kanade.tachiyomi.network
import com.squareup.duktape.Duktape import com.squareup.duktape.Duktape
import okhttp3.CacheControl
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Request import okhttp3.Request
@ -21,7 +22,7 @@ class CloudflareInterceptor : Interceptor {
val response = chain.proceed(chain.request()) val response = chain.proceed(chain.request())
// Check if Cloudflare anti-bot is on // Check if Cloudflare anti-bot is on
if (response.code() == 503 && serverCheck.contains(response.header("Server"))) { if (response.code() == 503 && response.header("Server") in serverCheck) {
return chain.proceed(resolveChallenge(response)) return chain.proceed(resolveChallenge(response))
} }
@ -43,31 +44,32 @@ class CloudflareInterceptor : Interceptor {
val pass = passPattern.find(content)?.groups?.get(1)?.value val pass = passPattern.find(content)?.groups?.get(1)?.value
if (operation == null || challenge == null || pass == null) { if (operation == null || challenge == null || pass == null) {
throw RuntimeException("Failed resolving Cloudflare challenge") throw Exception("Failed resolving Cloudflare challenge")
} }
val js = operation val js = operation
.replace(Regex("""a\.value =(.+?) \+.*"""), "$1") .replace(Regex("""a\.value = (.+ \+ t\.length).+"""), "$1")
.replace(Regex("""\s{3,}[a-z](?: = |\.).+"""), "") .replace(Regex("""\s{3,}[a-z](?: = |\.).+"""), "")
.replace("t.length", "${domain.length}")
.replace("\n", "") .replace("\n", "")
val result = (duktape.evaluate(js) as Double).toInt() val result = duktape.evaluate(js) as Double
val answer = "${result + domain.length}"
val cloudflareUrl = HttpUrl.parse("${url.scheme()}://$domain/cdn-cgi/l/chk_jschl")!! val cloudflareUrl = HttpUrl.parse("${url.scheme()}://$domain/cdn-cgi/l/chk_jschl")!!
.newBuilder() .newBuilder()
.addQueryParameter("jschl_vc", challenge) .addQueryParameter("jschl_vc", challenge)
.addQueryParameter("pass", pass) .addQueryParameter("pass", pass)
.addQueryParameter("jschl_answer", answer) .addQueryParameter("jschl_answer", "$result")
.toString() .toString()
val cloudflareHeaders = originalRequest.headers() val cloudflareHeaders = originalRequest.headers()
.newBuilder() .newBuilder()
.add("Referer", url.toString()) .add("Referer", url.toString())
.add("Accept", "text/html,application/xhtml+xml,application/xml")
.add("Accept-Language", "en")
.build() .build()
return GET(cloudflareUrl, cloudflareHeaders) return GET(cloudflareUrl, cloudflareHeaders, cache = CacheControl.Builder().build())
} }
} }

View File

@ -1,9 +1,22 @@
package eu.kanade.tachiyomi.network package eu.kanade.tachiyomi.network
import android.content.Context import android.content.Context
import android.os.Build
import okhttp3.Cache import okhttp3.Cache
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import java.io.File import java.io.File
import java.io.IOException
import java.net.InetAddress
import java.net.Socket
import java.net.UnknownHostException
import java.security.KeyManagementException
import java.security.KeyStore
import java.security.NoSuchAlgorithmException
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
class NetworkHelper(context: Context) { class NetworkHelper(context: Context) {
@ -16,6 +29,7 @@ class NetworkHelper(context: Context) {
val client = OkHttpClient.Builder() val client = OkHttpClient.Builder()
.cookieJar(cookieManager) .cookieJar(cookieManager)
.cache(Cache(cacheDir, cacheSize)) .cache(Cache(cacheDir, cacheSize))
.enableTLS12()
.build() .build()
val cloudflareClient = client.newBuilder() val cloudflareClient = client.newBuilder()
@ -25,4 +39,75 @@ class NetworkHelper(context: Context) {
val cookies: PersistentCookieStore val cookies: PersistentCookieStore
get() = cookieManager.store get() = cookieManager.store
private fun OkHttpClient.Builder.enableTLS12(): OkHttpClient.Builder {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
return this
}
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(null as KeyStore?)
val trustManagers = trustManagerFactory.trustManagers
if (trustManagers.size == 1 && trustManagers[0] is X509TrustManager) {
class TLSSocketFactory @Throws(KeyManagementException::class, NoSuchAlgorithmException::class)
constructor() : SSLSocketFactory() {
private val internalSSLSocketFactory: SSLSocketFactory
init {
val context = SSLContext.getInstance("TLS")
context.init(null, null, null)
internalSSLSocketFactory = context.socketFactory
}
override fun getDefaultCipherSuites(): Array<String> {
return internalSSLSocketFactory.defaultCipherSuites
}
override fun getSupportedCipherSuites(): Array<String> {
return internalSSLSocketFactory.supportedCipherSuites
}
@Throws(IOException::class)
override fun createSocket(): Socket? {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket())
}
@Throws(IOException::class)
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket? {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose))
}
@Throws(IOException::class, UnknownHostException::class)
override fun createSocket(host: String, port: Int): Socket? {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port))
}
@Throws(IOException::class, UnknownHostException::class)
override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket? {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort))
}
@Throws(IOException::class)
override fun createSocket(host: InetAddress, port: Int): Socket? {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port))
}
@Throws(IOException::class)
override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket? {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort))
}
private fun enableTLSOnSocket(socket: Socket?): Socket? {
if (socket != null && socket is SSLSocket) {
socket.enabledProtocols = socket.supportedProtocols
}
return socket
}
}
sslSocketFactory(TLSSocketFactory(), trustManagers[0] as X509TrustManager)
}
return this
}
} }

View File

@ -24,4 +24,8 @@ class Batoto : Source {
return Observable.error(Exception("RIP Batoto")) return Observable.error(Exception("RIP Batoto"))
} }
override fun toString(): String {
return "$name (EN)"
}
} }

View File

@ -49,7 +49,11 @@ class Mangachan : ParsedHttpSource() {
} }
} }
} }
is OrderBy -> { if (filter.state!!.ascending && filter.state!!.index == 0) { statusParam = false } } is OrderBy -> {
if (filter.state!!.ascending && filter.state!!.index == 0) {
statusParam = false
}
}
is Status -> status = arrayOf("", "all_done", "end", "ongoing", "new_ch")[filter.state] is Status -> status = arrayOf("", "all_done", "end", "ongoing", "new_ch")[filter.state]
} }
} }
@ -103,6 +107,7 @@ class Mangachan : ParsedHttpSource() {
override fun popularMangaFromElement(element: Element): SManga { override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.thumbnail_url = element.select("div.manga_images img").first().attr("src")
element.select("h2 > a").first().let { element.select("h2 > a").first().let {
manga.setUrlWithoutDomain(it.attr("href")) manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.text() manga.title = it.text()
@ -220,32 +225,22 @@ class Mangachan : ParsedHttpSource() {
GenreList(getGenreList()) GenreList(getGenreList())
) )
// private class StatusList(status: List<Status>) : Filter.Group<Status>("Статус", status)
// private class Status(name: String, val id: String) : Filter.CheckBox(name, false)
// private fun getStatusList() = listOf(
// Status("Перевод завершен", "/all_done"),
// Status("Выпуск завершен", "/end"),
// Status("Онгоинг", "/ongoing"),
// Status("Новые главы", "/new_ch")
// )
/* [...document.querySelectorAll("li.sidetag > a:nth-child(1)")]
/* [...document.querySelectorAll("li.sidetag > a:nth-child(1)")].map((el,i) => * .map(el => `Genre("${el.getAttribute('href').substr(6)}")`).join(',\n')
* { const link=el.getAttribute('href');const id=link.substr(6,link.length);
* return `Genre("${id.replace("_", " ")}")` }).join(',\n')
* on http://mangachan.me/ * on http://mangachan.me/
*/ */
private fun getGenreList() = listOf( private fun getGenreList() = listOf(
Genre("18 плюс"), Genre("18_плюс"),
Genre("bdsm"), Genre("bdsm"),
Genre("арт"), Genre("арт"),
Genre("боевик"), Genre("боевик"),
Genre("боевые искусства"), Genre("боевые_искусства"),
Genre("вампиры"), Genre("вампиры"),
Genre("веб"), Genre("веб"),
Genre("гарем"), Genre("гарем"),
Genre("гендерная интрига"), Genre("гендерная_интрига"),
Genre("героическое фэнтези"), Genre("героическое_фэнтези"),
Genre("детектив"), Genre("детектив"),
Genre("дзёсэй"), Genre("дзёсэй"),
Genre("додзинси"), Genre("додзинси"),
@ -262,13 +257,13 @@ class Mangachan : ParsedHttpSource() {
Genre("меха"), Genre("меха"),
Genre("мистика"), Genre("мистика"),
Genre("музыка"), Genre("музыка"),
Genre("научная фантастика"), Genre("научная_фантастика"),
Genre("повседневность"), Genre("повседневность"),
Genre("постапокалиптика"), Genre("постапокалиптика"),
Genre("приключения"), Genre("приключения"),
Genre("психология"), Genre("психология"),
Genre("романтика"), Genre("романтика"),
Genre("самурайский боевик"), Genre("самурайский_боевик"),
Genre("сборник"), Genre("сборник"),
Genre("сверхъестественное"), Genre("сверхъестественное"),
Genre("сказка"), Genre("сказка"),
@ -279,7 +274,6 @@ class Mangachan : ParsedHttpSource() {
Genre("сёдзё-ай"), Genre("сёдзё-ай"),
Genre("сёнэн"), Genre("сёнэн"),
Genre("сёнэн-ай"), Genre("сёнэн-ай"),
Genre("темное фэнтези"),
Genre("тентакли"), Genre("тентакли"),
Genre("трагедия"), Genre("трагедия"),
Genre("триллер"), Genre("триллер"),

View File

@ -24,23 +24,19 @@ class Mintmanga : ParsedHttpSource() {
override val supportsLatest = true override val supportsLatest = true
override fun headersBuilder() = Headers.Builder().apply {
add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64)")
add("Referer", baseUrl)
}
override fun popularMangaRequest(page: Int): Request = override fun popularMangaRequest(page: Int): Request =
GET("$baseUrl/list?sortType=rate&offset=${70 * (page - 1)}&max=70", headers) GET("$baseUrl/list?sortType=rate&offset=${70 * (page - 1)}&max=70", headers)
override fun latestUpdatesRequest(page: Int): Request = override fun latestUpdatesRequest(page: Int): Request =
GET("$baseUrl/list?sortType=updated&offset=${70 * (page - 1)}&max=70", headers) GET("$baseUrl/list?sortType=updated&offset=${70 * (page - 1)}&max=70", headers)
override fun popularMangaSelector() = "div.desc" override fun popularMangaSelector() = "div.tile"
override fun latestUpdatesSelector() = "div.desc" override fun latestUpdatesSelector() = "div.tile"
override fun popularMangaFromElement(element: Element): SManga { override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.thumbnail_url = element.select("img.lazy").first().attr("data-original")
element.select("h3 > a").first().let { element.select("h3 > a").first().let {
manga.setUrlWithoutDomain(it.attr("href")) manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.attr("title") manga.title = it.attr("title")
@ -90,10 +86,15 @@ class Mintmanga : ParsedHttpSource() {
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
val urlElement = element.select("a").first() val urlElement = element.select("a").first()
val urlText = urlElement.text()
val chapter = SChapter.create() val chapter = SChapter.create()
chapter.setUrlWithoutDomain(urlElement.attr("href") + "?mature=1") chapter.setUrlWithoutDomain(urlElement.attr("href") + "?mtr=1")
chapter.name = urlElement.text().replace(" новое", "") if (urlText.endsWith(" новое")) {
chapter.name = urlText.dropLast(6)
} else {
chapter.name = urlText
}
chapter.date_upload = element.select("td:eq(1)").first()?.text()?.let { chapter.date_upload = element.select("td:eq(1)").first()?.text()?.let {
SimpleDateFormat("dd/MM/yy", Locale.US).parse(it).time SimpleDateFormat("dd/MM/yy", Locale.US).parse(it).time
} ?: 0 } ?: 0
@ -143,11 +144,19 @@ class Mintmanga : ParsedHttpSource() {
override fun imageUrlParse(document: Document) = "" override fun imageUrlParse(document: Document) = ""
override fun imageRequest(page: Page): Request {
val imgHeader = Headers.Builder().apply {
add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64)")
add("Referer", baseUrl)
}.build()
return GET(page.imageUrl!!, imgHeader)
}
private class Genre(name: String, val id: String) : Filter.TriState(name) private class Genre(name: String, val id: String) : Filter.TriState(name)
/* [...document.querySelectorAll("tr.advanced_option:nth-child(1) > td:nth-child(3) span.js-link")].map((el,i) => { /* [...document.querySelectorAll("tr.advanced_option:nth-child(1) > td:nth-child(3) span.js-link")]
* const onClick=el.getAttribute('onclick');const id=onClick.substr(31,onClick.length-33); * .map(el => `Genre("${el.textContent.trim()}", $"{el.getAttribute('onclick')
* return `Genre("${el.textContent.trim()}", "${id}")` }).join(',\n') * .substr(31,el.getAttribute('onclick').length-33)"})`).join(',\n')
* on http://mintmanga.com/search/advanced * on http://mintmanga.com/search/advanced
*/ */
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(

View File

@ -24,14 +24,9 @@ class Readmanga : ParsedHttpSource() {
override val supportsLatest = true override val supportsLatest = true
override fun headersBuilder() = Headers.Builder().apply { override fun popularMangaSelector() = "div.tile"
add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64)")
add("Referer", baseUrl)
}
override fun popularMangaSelector() = "div.desc" override fun latestUpdatesSelector() = "div.tile"
override fun latestUpdatesSelector() = "div.desc"
override fun popularMangaRequest(page: Int): Request = override fun popularMangaRequest(page: Int): Request =
GET("$baseUrl/list?sortType=rate&offset=${70 * (page - 1)}&max=70", headers) GET("$baseUrl/list?sortType=rate&offset=${70 * (page - 1)}&max=70", headers)
@ -41,6 +36,7 @@ class Readmanga : ParsedHttpSource() {
override fun popularMangaFromElement(element: Element): SManga { override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.thumbnail_url = element.select("img.lazy").first().attr("data-original")
element.select("h3 > a").first().let { element.select("h3 > a").first().let {
manga.setUrlWithoutDomain(it.attr("href")) manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.attr("title") manga.title = it.attr("title")
@ -90,10 +86,15 @@ class Readmanga : ParsedHttpSource() {
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
val urlElement = element.select("a").first() val urlElement = element.select("a").first()
val urlText = urlElement.text()
val chapter = SChapter.create() val chapter = SChapter.create()
chapter.setUrlWithoutDomain(urlElement.attr("href") + "?mature=1") chapter.setUrlWithoutDomain(urlElement.attr("href") + "?mtr=1")
chapter.name = urlElement.text().replace(" новое", "") if (urlText.endsWith(" новое")) {
chapter.name = urlText.dropLast(6)
} else {
chapter.name = urlText
}
chapter.date_upload = element.select("td:eq(1)").first()?.text()?.let { chapter.date_upload = element.select("td:eq(1)").first()?.text()?.let {
SimpleDateFormat("dd/MM/yy", Locale.US).parse(it).time SimpleDateFormat("dd/MM/yy", Locale.US).parse(it).time
} ?: 0 } ?: 0
@ -143,11 +144,19 @@ class Readmanga : ParsedHttpSource() {
override fun imageUrlParse(document: Document) = "" override fun imageUrlParse(document: Document) = ""
override fun imageRequest(page: Page): Request {
val imgHeader = Headers.Builder().apply {
add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64)")
add("Referer", baseUrl)
}.build()
return GET(page.imageUrl!!, imgHeader)
}
private class Genre(name: String, val id: String) : Filter.TriState(name) private class Genre(name: String, val id: String) : Filter.TriState(name)
/* [...document.querySelectorAll("tr.advanced_option:nth-child(1) > td:nth-child(3) span.js-link")].map((el,i) => { /* [...document.querySelectorAll("tr.advanced_option:nth-child(1) > td:nth-child(3) span.js-link")]
* const onClick=el.getAttribute('onclick');const id=onClick.substr(31,onClick.length-33); * .map(el => `Genre("${el.textContent.trim()}", $"{el.getAttribute('onclick')
* return `Genre("${el.textContent.trim()}", "${id}")` }).join(',\n') * .substr(31,el.getAttribute('onclick').length-33)"})`).join(',\n')
* on http://readmanga.me/search/advanced * on http://readmanga.me/search/advanced
*/ */
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(

View File

@ -28,7 +28,7 @@ public class NucleusConductorDelegate<P extends Presenter> {
Bundle onSaveInstanceState() { Bundle onSaveInstanceState() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
getPresenter(); // getPresenter(); // Workaround a crash related to saving instance state with child routers
if (presenter != null) { if (presenter != null) {
presenter.save(bundle); presenter.save(bundle);
} }

View File

@ -34,7 +34,7 @@ class LibraryCategoryAdapter(view: LibraryCategoryView) :
* @param manga the manga to find. * @param manga the manga to find.
*/ */
fun indexOf(manga: Manga): Int { fun indexOf(manga: Manga): Int {
return mangas.indexOfFirst { it.manga.id == manga.id } return currentItems.indexOfFirst { it.manga.id == manga.id }
} }
fun performFilter() { fun performFilter() {

View File

@ -73,7 +73,7 @@ class LibraryController(
/** /**
* Currently selected mangas. * Currently selected mangas.
*/ */
val selectedMangas = mutableListOf<Manga>() val selectedMangas = mutableSetOf<Manga>()
private var selectedCoverManga: Manga? = null private var selectedCoverManga: Manga? = null
@ -429,13 +429,15 @@ class LibraryController(
*/ */
fun setSelection(manga: Manga, selected: Boolean) { fun setSelection(manga: Manga, selected: Boolean) {
if (selected) { if (selected) {
selectedMangas.add(manga) if (selectedMangas.add(manga)) {
selectionRelay.call(LibrarySelectionEvent.Selected(manga)) selectionRelay.call(LibrarySelectionEvent.Selected(manga))
}
} else { } else {
selectedMangas.remove(manga) if (selectedMangas.remove(manga)) {
selectionRelay.call(LibrarySelectionEvent.Unselected(manga)) selectionRelay.call(LibrarySelectionEvent.Unselected(manga))
} }
} }
}
/** /**
* Move the selected manga to a list of categories. * Move the selected manga to a list of categories.

View File

@ -261,7 +261,11 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
} }
fun setLastUpdateDate(date: Date) { fun setLastUpdateDate(date: Date) {
if (date.time != 0L) {
manga_last_update?.text = DateFormat.getDateInstance(DateFormat.SHORT).format(date) manga_last_update?.text = DateFormat.getDateInstance(DateFormat.SHORT).format(date)
} else {
manga_last_update?.text = resources?.getString(R.string.unknown)
}
} }
/** /**

View File

@ -8,9 +8,9 @@ import com.jakewharton.rxbinding.widget.itemClicks
import com.jakewharton.rxbinding.widget.textChanges import com.jakewharton.rxbinding.widget.textChanges
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.plusAssign import eu.kanade.tachiyomi.util.plusAssign
import kotlinx.android.synthetic.main.track_search_dialog.view.* import kotlinx.android.synthetic.main.track_search_dialog.view.*
@ -114,14 +114,14 @@ class TrackSearchDialog : DialogController {
private fun search(query: String) { private fun search(query: String) {
val view = dialogView ?: return val view = dialogView ?: return
view.progress.visibility = View.VISIBLE view.progress.visibility = View.VISIBLE
view.track_search_list.visibility = View.GONE view.track_search_list.visibility = View.INVISIBLE
trackController.presenter.search(query, service) trackController.presenter.search(query, service)
} }
fun onSearchResults(results: List<TrackSearch>) { fun onSearchResults(results: List<TrackSearch>) {
selectedItem = null selectedItem = null
val view = dialogView ?: return val view = dialogView ?: return
view.progress.visibility = View.GONE view.progress.visibility = View.INVISIBLE
view.track_search_list.visibility = View.VISIBLE view.track_search_list.visibility = View.VISIBLE
adapter?.setItems(results) adapter?.setItems(results)
} }
@ -129,7 +129,7 @@ class TrackSearchDialog : DialogController {
fun onSearchResultsError() { fun onSearchResultsError() {
val view = dialogView ?: return val view = dialogView ?: return
view.progress.visibility = View.VISIBLE view.progress.visibility = View.VISIBLE
view.track_search_list.visibility = View.GONE view.track_search_list.visibility = View.INVISIBLE
adapter?.setItems(emptyList()) adapter?.setItems(emptyList())
} }

View File

@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.util.plusAssign import eu.kanade.tachiyomi.util.plusAssign
import eu.kanade.tachiyomi.util.visibleIf
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
import kotlinx.android.synthetic.main.reader_settings_dialog.view.* import kotlinx.android.synthetic.main.reader_settings_dialog.view.*
import rx.Observable import rx.Observable
@ -91,6 +92,23 @@ class ReaderSettingsDialog : DialogFragment() {
crop_borders.setOnCheckedChangeListener { _, isChecked -> crop_borders.setOnCheckedChangeListener { _, isChecked ->
preferences.cropBorders().set(isChecked) preferences.cropBorders().set(isChecked)
} }
crop_borders_webtoon.isChecked = preferences.cropBordersWebtoon().getOrDefault()
crop_borders_webtoon.setOnCheckedChangeListener { _, isChecked ->
preferences.cropBordersWebtoon().set(isChecked)
}
val readerActivity = activity as? ReaderActivity
val isWebtoonViewer = if (readerActivity != null) {
val mangaViewer = readerActivity.presenter.manga.viewer
val viewer = if (mangaViewer == 0) preferences.defaultViewer() else mangaViewer
viewer == ReaderActivity.WEBTOON
} else {
false
}
crop_borders.visibleIf { !isWebtoonViewer }
crop_borders_webtoon.visibleIf { isWebtoonViewer }
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -4,7 +4,12 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.view.* import android.view.Display
import android.view.GestureDetector
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
@ -123,7 +128,7 @@ class WebtoonReader : BaseReader() {
.distinctUntilChanged() .distinctUntilChanged()
.subscribe { refreshAdapter() }) .subscribe { refreshAdapter() })
subscriptions.add(readerActivity.preferences.cropBorders() subscriptions.add(readerActivity.preferences.cropBordersWebtoon()
.asObservable() .asObservable()
.doOnNext { cropBorders = it } .doOnNext { cropBorders = it }
.skip(1) .skip(1)

View File

@ -126,6 +126,7 @@ class SettingsAboutController : SettingsController() {
} }
} }
}, { error -> }, { error ->
activity?.toast(error.message)
Timber.e(error) Timber.e(error)
}) })
} }

View File

@ -29,8 +29,9 @@ class SettingsGeneralController : SettingsController() {
listPreference { listPreference {
key = Keys.lang key = Keys.lang
titleRes = R.string.pref_language titleRes = R.string.pref_language
entryValues = arrayOf("", "ar", "bg", "bn", "de", "en", "es", "fr", "hi", "hu", "id", entryValues = arrayOf("", "ar", "bg", "bn", "de", "en-US", "en-GB", "es", "fr", "hi",
"it", "ja", "ko", "lv", "ms", "nl", "pl", "pt", "pt-BR", "ro", "ru", "vi") "hu", "id", "it", "ja", "ko", "lv", "ms", "nl", "pl", "pt", "pt-BR", "ro",
"ru", "vi")
entries = entryValues.map { value -> entries = entryValues.map { value ->
val locale = LocaleHelper.getLocaleFromString(value.toString()) val locale = LocaleHelper.getLocaleFromString(value.toString())
locale?.getDisplayName(locale)?.capitalize() ?: locale?.getDisplayName(locale)?.capitalize() ?:

View File

@ -76,8 +76,8 @@ class SettingsReaderController : SettingsController() {
defaultValue = true defaultValue = true
} }
switchPreference { switchPreference {
key = Keys.enableTransitions key = Keys.keepScreenOn
titleRes = R.string.pref_page_transitions titleRes = R.string.pref_keep_screen_on
defaultValue = true defaultValue = true
} }
switchPreference { switchPreference {
@ -85,15 +85,28 @@ class SettingsReaderController : SettingsController() {
titleRes = R.string.pref_show_page_number titleRes = R.string.pref_show_page_number
defaultValue = true defaultValue = true
} }
preferenceCategory {
titleRes = R.string.pager_viewer
switchPreference {
key = Keys.enableTransitions
titleRes = R.string.pref_page_transitions
defaultValue = true
}
switchPreference { switchPreference {
key = Keys.cropBorders key = Keys.cropBorders
titleRes = R.string.pref_crop_borders titleRes = R.string.pref_crop_borders
defaultValue = false defaultValue = false
} }
}
preferenceCategory {
titleRes = R.string.webtoon_viewer
switchPreference { switchPreference {
key = Keys.keepScreenOn key = Keys.cropBordersWebtoon
titleRes = R.string.pref_keep_screen_on titleRes = R.string.pref_crop_borders
defaultValue = true defaultValue = false
}
} }
preferenceCategory { preferenceCategory {
titleRes = R.string.pref_reader_navigation titleRes = R.string.pref_reader_navigation

View File

@ -36,7 +36,7 @@ fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT)
* @param duration the duration of the toast. Defaults to short. * @param duration the duration of the toast. Defaults to short.
*/ */
fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT) { fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, text, duration).show() Toast.makeText(this, text.orEmpty(), duration).show()
} }
/** /**

View File

@ -47,6 +47,10 @@ inline fun View.gone() {
visibility = View.GONE visibility = View.GONE
} }
inline fun View.visibleIf(block: () -> Boolean) {
visibility = if (block()) View.VISIBLE else View.GONE
}
/** /**
* Returns a TextDrawable determined by input * Returns a TextDrawable determined by input
* *

View File

@ -105,7 +105,7 @@
tools:text="122" tools:text="122"
tools:visibility="visible" tools:visibility="visible"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
app:layout_constraintRight_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"

View File

@ -63,7 +63,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_more_vert_black_24dp" app:srcCompat="@drawable/ic_more_vert_black_24dp"
app:layout_constraintRight_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:paddingStart="24dp" android:paddingStart="24dp"
android:paddingEnd="16dp" android:paddingEnd="16dp"
@ -82,7 +82,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="DOWNLOADED" tools:text="DOWNLOADED"
android:textAllCaps="true" android:textAllCaps="true"
app:layout_constraintRight_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginRight="16dp"/> android:layout_marginRight="16dp"/>

View File

@ -27,13 +27,16 @@
<TextView <TextView
android:id="@+id/ext_title" android:id="@+id/ext_title"
style="@style/TextAppearance.Regular" style="@style/TextAppearance.Regular"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginRight="4dp"
android:layout_marginEnd="4dp"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:textAppearance="@style/TextAppearance.Regular.SubHeading" android:textAppearance="@style/TextAppearance.Regular.SubHeading"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintStart_toEndOf="@id/image" app:layout_constraintStart_toEndOf="@id/image"
app:layout_constraintEnd_toStartOf="@id/ext_button"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/lang" app:layout_constraintBottom_toTopOf="@id/lang"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"

View File

@ -259,32 +259,38 @@
<android.support.v4.widget.NestedScrollView <android.support.v4.widget.NestedScrollView
android:id="@+id/description_scrollview" android:id="@+id/description_scrollview"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toTopOf="@id/manga_genres_tags"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/manga_summary_label" app:layout_constraintTop_toBottomOf="@id/manga_summary_label"
app:layout_constraintBottom_toTopOf="@id/manga_genres_tags"> app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed">
<TextView <TextView
android:id="@+id/manga_summary" android:id="@+id/manga_summary"
style="@style/TextAppearance.Regular.Body1.Secondary" style="@style/TextAppearance.Regular.Body1.Secondary"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textIsSelectable="false"/> android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:textIsSelectable="false" />
</android.support.v4.widget.NestedScrollView> </android.support.v4.widget.NestedScrollView>
<me.gujun.android.taggroup.TagGroup <me.gujun.android.taggroup.TagGroup
android:id="@+id/manga_genres_tags" android:id="@+id/manga_genres_tags"
style="@style/TagGroup" style="@style/TagGroup"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constrainedHeight="true"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/description_scrollview" app:layout_constraintTop_toBottomOf="@id/description_scrollview"

View File

@ -171,6 +171,12 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/pref_crop_borders"/> android:text="@string/pref_crop_borders"/>
<android.support.v7.widget.SwitchCompat
android:id="@+id/crop_borders_webtoon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/pref_crop_borders"/>
<android.support.v7.widget.SwitchCompat <android.support.v7.widget.SwitchCompat
android:id="@+id/fullscreen" android:id="@+id/fullscreen"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" 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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<EditText <EditText
@ -14,8 +13,13 @@
android:hint="@string/title" android:hint="@string/title"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:maxLines="1" android:inputType="text"
app:layout_constraintTop_toTopOf="parent"/> android:maxLines="1"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ProgressBar <ProgressBar
android:id="@+id/progress" android:id="@+id/progress"
@ -24,11 +28,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="32dp" android:layout_marginBottom="32dp"
android:layout_marginTop="32dp" android:layout_marginTop="32dp"
android:visibility="gone" android:layout_gravity="center"
app:layout_constraintBottom_toTopOf="@id/divider1" android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/track_search"
tools:visibility="visible"/> tools:visibility="visible"/>
<ListView <ListView
@ -36,9 +37,8 @@
style="@style/Theme.Widget.CardView" style="@style/Theme.Widget.CardView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="40dp"
android:choiceMode="singleChoice"
android:clipToPadding="false" android:clipToPadding="false"
android:choiceMode="singleChoice"
android:divider="@null" android:divider="@null"
android:dividerHeight="10dp" android:dividerHeight="10dp"
android:footerDividersEnabled="true" android:footerDividersEnabled="true"
@ -47,19 +47,15 @@
android:paddingBottom="4dp" android:paddingBottom="4dp"
android:paddingTop="4dp" android:paddingTop="4dp"
android:scrollbars="none" android:scrollbars="none"
android:visibility="gone" android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/track_search"
tools:listitem="@layout/track_search_item" tools:listitem="@layout/track_search_item"
tools:visibility="visible"/> tools:visibility="visible"/>
</FrameLayout>
<View <View
android:id="@+id/divider1"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="1dp"
android:background="?android:attr/divider" android:background="?android:attr/divider"/>
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/track_search_list"/>
</android.support.constraint.ConstraintLayout> </LinearLayout>

View File

@ -12,7 +12,6 @@
android:layout_height="216dp" android:layout_height="216dp"
android:background="?attr/selectable_list_drawable" android:background="?attr/selectable_list_drawable"
android:orientation="horizontal"> android:orientation="horizontal">
>
<ImageView <ImageView
android:id="@+id/track_search_cover" android:id="@+id/track_search_cover"

View File

@ -1,5 +1,33 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<changelog bulletedList="true"> <changelog bulletedList="true">
<changelogversion versionName="v0.7.3" changeDate="">
<changelogtext>Fixed the tracking search layout when there are many results.</changelogtext>
<changelogtext>Separate english language into american and british so that dates are formatted according to that locale.</changelogtext>
<changelogtext>Added Firebase analytics, for Android API distribution.</changelogtext>
<changelogtext>Crop borders for webtoons now has a separate setting.</changelogtext>
<changelogtext>The downloader now runs in a foreground service to prevent it from being killed.</changelogtext>
<changelogtext>Fixed a few weird crashes.</changelogtext>
</changelogversion>
<changelogversion versionName="v0.7.2" changeDate="">
<changelogtext>Fixed missing downloaded label in chapters screen.</changelogtext>
<changelogtext>Fixed updater in KitKat and lower due to TLS.</changelogtext>
</changelogversion>
<changelogversion versionName="v0.7.1" changeDate="">
<changelogtext>Updated Cloudflare bypass.</changelogtext>
<changelogtext>Enabled TLS 1.1 and TLS 1.2 on Android KitKat and lower.</changelogtext>
<changelogtext>Minor UI changes.</changelogtext>
</changelogversion>
<changelogversion versionName="v0.7.0" changeDate=""> <changelogversion versionName="v0.7.0" changeDate="">
<changelogtext>Added extensions support. You can now install and update extensions within the app. <changelogtext>Added extensions support. You can now install and update extensions within the app.
If you installed any extension previously through F-Droid, you'll have to uninstall them first.</changelogtext> If you installed any extension previously through F-Droid, you'll have to uninstall them first.</changelogtext>

View File

@ -11,7 +11,7 @@
<string name="label_recent_updates">Nouveautés bibliothèque</string> <string name="label_recent_updates">Nouveautés bibliothèque</string>
<string name="label_latest_updates">Dernières nouveautés</string> <string name="label_latest_updates">Dernières nouveautés</string>
<string name="label_categories">Catégories</string> <string name="label_categories">Catégories</string>
<string name="label_selected">Sélectionné: %1$d</string> <string name="label_selected">Sélectionné : %1$d</string>
<string name="label_backup">Sauvegarde</string> <string name="label_backup">Sauvegarde</string>
<!-- Actions --> <!-- Actions -->
@ -57,7 +57,7 @@
<string name="action_retry">Réessayer</string> <string name="action_retry">Réessayer</string>
<string name="action_remove">Supprimer</string> <string name="action_remove">Supprimer</string>
<string name="action_resume">Reprendre</string> <string name="action_resume">Reprendre</string>
<string name="action_open_in_browser">Ouvre dans le navigateur</string> <string name="action_open_in_browser">Ouvrir dans le navigateur</string>
<string name="action_add_to_home_screen">Ajouter à l\'écran d\'accueil</string> <string name="action_add_to_home_screen">Ajouter à l\'écran d\'accueil</string>
<string name="action_display_mode">Changer le mode d\'affichage</string> <string name="action_display_mode">Changer le mode d\'affichage</string>
<string name="action_display">Affichage</string> <string name="action_display">Affichage</string>
@ -152,9 +152,9 @@
<string name="rotation_force_portrait">Forcer portrait</string> <string name="rotation_force_portrait">Forcer portrait</string>
<string name="rotation_force_landscape">Forcer paysage</string> <string name="rotation_force_landscape">Forcer paysage</string>
<string name="color_filter_r_value">R</string> <string name="color_filter_r_value">R</string>
<string name="color_filter_g_value">G</string> <string name="color_filter_g_value">V</string>
<string name="color_filter_b_value">B</string> <string name="color_filter_b_value">B</string>
<string name="color_filter_a_value">A</string> <string name="color_filter_a_value">O</string>
<!-- Downloads section --> <!-- Downloads section -->
@ -164,7 +164,7 @@
<string name="pref_remove_after_read">Supprimer après avoir lu</string> <string name="pref_remove_after_read">Supprimer après avoir lu</string>
<string name="disabled">Désactivé</string> <string name="disabled">Désactivé</string>
<string name="last_read_chapter">Dernier chapitre lu</string> <string name="last_read_chapter">Dernier chapitre lu</string>
<string name="second_to_last">Avant-dernier chapiture lu</string> <string name="second_to_last">Avant-dernier chapitre lu</string>
<string name="third_to_last">Du troisième au dernier chapitre</string> <string name="third_to_last">Du troisième au dernier chapitre</string>
<string name="fourth_to_last">Du quatrième au dernier chapitre</string> <string name="fourth_to_last">Du quatrième au dernier chapitre</string>
<string name="pref_download_new">Télécharger les nouveaux chapitres</string> <string name="pref_download_new">Télécharger les nouveaux chapitres</string>
@ -286,7 +286,7 @@
<!-- Reader activity --> <!-- Reader activity -->
<string name="custom_filter">Filtre personnalisé</string> <string name="custom_filter">Filtre personnalisé</string>
<string name="set_as_cover">Mettre comme couverture</string> <string name="set_as_cover">Ajouter comme couverture</string>
<string name="cover_updated">Couverture mise à jour</string> <string name="cover_updated">Couverture mise à jour</string>
<string name="page_downloaded">Page copiée vers %1$s</string> <string name="page_downloaded">Page copiée vers %1$s</string>
<string name="downloading">En cours de téléchargement…</string> <string name="downloading">En cours de téléchargement…</string>
@ -313,7 +313,7 @@
<string name="notification_update_progress">Progression mise à jour: %1$d/%2$d</string> <string name="notification_update_progress">Progression mise à jour: %1$d/%2$d</string>
<string name="notification_new_chapters">Des nouveaux chapitres ont été trouvés</string> <string name="notification_new_chapters">Des nouveaux chapitres ont été trouvés</string>
<string name="notification_cover_update_failed">La mise à jour de la couverture a échoué</string> <string name="notification_cover_update_failed">La mise à jour de la couverture a échoué</string>
<string name="notification_first_add_to_library">Veuillez ajouter le manga dans votre bibliothèque avant de faire cela</string> <string name="notification_first_add_to_library">Veuillez ajouter le manga dans votre bibliothèque avant</string>
<string name="notification_not_connected_to_ac_body">Non branché</string> <string name="notification_not_connected_to_ac_body">Non branché</string>
<string name="notification_no_connection_title">Synchronisation annulée</string> <string name="notification_no_connection_title">Synchronisation annulée</string>
<string name="notification_no_connection_body">Connexion non disponible</string> <string name="notification_no_connection_body">Connexion non disponible</string>
@ -324,15 +324,15 @@
<string name="file_select_icon">Sélectionner une icône de raccourci</string> <string name="file_select_icon">Sélectionner une icône de raccourci</string>
<!--UpdateCheck--> <!--UpdateCheck-->
<string name="update_check_title">Nouvelle mise à jour disponible!</string> <string name="update_check_title">Nouvelle mise à jour disponible !</string>
<string name="update_check_confirm">Télécharger</string> <string name="update_check_confirm">Télécharger</string>
<string name="update_check_ignore">Ignorer</string> <string name="update_check_ignore">Ignorer</string>
<string name="update_check_no_new_updates">Aucun mise à jour disponible</string> <string name="update_check_no_new_updates">Aucune mise à jour disponible</string>
<string name="update_check_download_started">Téléchargement commencé</string> <string name="update_check_download_started">Téléchargement commencé</string>
<string name="update_check_look_for_updates">Vérification des mises à jour</string> <string name="update_check_look_for_updates">Vérification des mises à jour</string>
<!--UpdateCheck Notifications--> <!--UpdateCheck Notifications-->
<string name="update_check_notification_file_download">Télécharger mise à jour</string> <string name="update_check_notification_file_download">Télécharger la mise à jour</string>
<string name="update_check_notification_download_in_progress">Téléchargement en cours</string> <string name="update_check_notification_download_in_progress">Téléchargement en cours</string>
<string name="update_check_notification_download_complete">Téléchargement terminé</string> <string name="update_check_notification_download_complete">Téléchargement terminé</string>
<string name="update_check_notification_download_error">Erreur lors du téléchargement</string> <string name="update_check_notification_download_error">Erreur lors du téléchargement</string>
@ -400,12 +400,12 @@
<string name="pref_backup_directory">Dossier de sauvegarde</string> <string name="pref_backup_directory">Dossier de sauvegarde</string>
<string name="pref_backup_service_category">Service</string> <string name="pref_backup_service_category">Service</string>
<string name="source_not_found">Source introuvable</string> <string name="source_not_found">Source introuvable</string>
<string name="restore_completed">Restauration terminé</string> <string name="restore_completed">Restauration terminée</string>
<string name="error_opening_log">Impossible d\'ouvrir le fichier journal</string> <string name="error_opening_log">Impossible d\'ouvrir le fichier journal</string>
<string name="file_saved">Fichier enregistré dans %1$s</string> <string name="file_saved">Fichier enregistré dans %1$s</string>
<string name="backup_choice">Que voulez-vous sauvegarder?</string> <string name="backup_choice">Que voulez-vous sauvegarder ?</string>
<string name="invalid_combination">Le défaut ne peut pas être selectionné avec des autres catégories</string> <string name="invalid_combination">Le défaut ne peut pas être selectionné avec des autres catégories</string>
<string name="delete_downloads_for_manga">Supprimer les chapitres téléchargés?</string> <string name="delete_downloads_for_manga">Supprimer les chapitres téléchargés ?</string>
<string name="notification_new_chapters_text">Pour %1$s chapitres</string> <string name="notification_new_chapters_text">Pour %1$s chapitres</string>
<string name="track">Suivi</string> <string name="track">Suivi</string>
@ -439,7 +439,7 @@
<string name="pref_read_with_volume_keys_inverted">Inverse les boutons de volume</string> <string name="pref_read_with_volume_keys_inverted">Inverse les boutons de volume</string>
<string name="pref_crop_borders">Rogner les bordures</string> <string name="pref_crop_borders">Rogner les bordures</string>
<string name="backup_restore_content">La restauration utilise le source pour obtenir des données, des frais de l\'opérateur peuvent s\'appliquer. <string name="backup_restore_content">La restauration utilise la source pour obtenir des données, des frais de l\'opérateur peuvent s\'appliquer.
Assurez-vous que vous êtes connecté à des sources qui le demande avant de commencer la restauration.</string> Assurez-vous que vous êtes connecté à des sources qui le demande avant de commencer la restauration.</string>
<string name="action_global_search">Recherche globale</string> <string name="action_global_search">Recherche globale</string>
<string name="action_open">Ouvrir</string> <string name="action_open">Ouvrir</string>
@ -447,7 +447,7 @@ Assurez-vous que vous êtes connecté à des sources qui le demande avant de com
<string name="other_source">Autre</string> <string name="other_source">Autre</string>
<string name="action_global_search_hint">Recherche globale…</string> <string name="action_global_search_hint">Recherche globale…</string>
<string name="no_results">Aucun résultat!</string> <string name="no_results">Aucun résultat !</string>
<string name="latest">Récents</string> <string name="latest">Récents</string>
<string name="browse">Explorer</string> <string name="browse">Explorer</string>

View File

@ -27,7 +27,7 @@
<!-- Attributes specific for SDK 21 and up --> <!-- Attributes specific for SDK 21 and up -->
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item> <item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@color/colorAmoled</item> <item name="android:navigationBarColor">@color/colorAmoledPrimary</item>
</style> </style>
<!--==============--> <!--==============-->

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Application Colors --> <!-- Application Colors -->
<color name="colorPrimary">#54759e</color> <color name="colorPrimary">#54759E</color>
<color name="colorPrimaryDark">#435e7e</color> <color name="colorPrimaryDark">#435E7E</color>
<!-- Dark Application Colors --> <!-- Dark Application Colors -->
<color name="colorDarkPrimary">#212121</color> <color name="colorDarkPrimary">#212121</color>
<color name="colorDarkPrimaryDark">#1c1c1d</color> <color name="colorDarkPrimaryDark">#1C1C1D</color>
<color name="colorAmoled">@color/md_black_1000</color> <color name="colorAmoledPrimary">@color/md_black_1000</color>
<!-- Light Theme --> <!-- Light Theme -->
<color name="colorAccentLight">@color/md_blue_A400</color> <color name="colorAccentLight">@color/md_blue_A400</color>
@ -27,7 +27,7 @@
<color name="iconColorLight">@color/md_black_1000</color> <color name="iconColorLight">@color/md_black_1000</color>
<!-- Dark Theme --> <!-- Dark Theme -->
<color name="colorAccentDark">#3399ff</color> <color name="colorAccentDark">#3399FF</color>
<color name="textColorPrimaryDark">@color/md_white_1000</color> <color name="textColorPrimaryDark">@color/md_white_1000</color>
<color name="textColorSecondaryDark">@color/md_white_1000_70</color> <color name="textColorSecondaryDark">@color/md_white_1000_70</color>
<color name="textColorHintDark">@color/md_white_1000_50</color> <color name="textColorHintDark">@color/md_white_1000_50</color>
@ -36,7 +36,7 @@
<color name="statusBarDark">@color/md_black_1000</color> <color name="statusBarDark">@color/md_black_1000</color>
<color name="appBarDark">@color/md_grey_900</color> <color name="appBarDark">@color/md_grey_900</color>
<color name="backgroundDark">#1c1c1d</color> <color name="backgroundDark">@color/colorDarkPrimaryDark</color>
<color name="dialogDark">@color/colorDarkPrimary</color> <color name="dialogDark">@color/colorDarkPrimary</color>
<color name="dialog_amoled">@color/colorDarkPrimaryDark</color> <color name="dialog_amoled">@color/colorDarkPrimaryDark</color>

View File

@ -190,6 +190,7 @@
<string name="right_to_left_viewer">Right to left</string> <string name="right_to_left_viewer">Right to left</string>
<string name="vertical_viewer">Vertical</string> <string name="vertical_viewer">Vertical</string>
<string name="webtoon_viewer">Webtoon</string> <string name="webtoon_viewer">Webtoon</string>
<string name="pager_viewer">Pager</string>
<string name="pref_image_decoder">Image decoder</string> <string name="pref_image_decoder">Image decoder</string>
<string name="pref_image_scale_type">Scale type</string> <string name="pref_image_scale_type">Scale type</string>
<string name="scale_type_fit_screen">Fit screen</string> <string name="scale_type_fit_screen">Fit screen</string>

View File

@ -66,6 +66,7 @@
<item name="actionBarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item> <item name="actionBarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
<item name="actionBarPopupTheme">@style/ThemeOverlay.AppCompat</item> <item name="actionBarPopupTheme">@style/ThemeOverlay.AppCompat</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.Material</item> <item name="preferenceTheme">@style/PreferenceThemeOverlay.Material</item>
<item name="md_background_color">@color/dialogDark</item>
<item name="alertDialogTheme">@style/Theme.AlertDialog.Dark</item> <item name="alertDialogTheme">@style/Theme.AlertDialog.Dark</item>
@ -86,8 +87,8 @@
<!-- Amoled Theme --> <!-- Amoled Theme -->
<!--==============--> <!--==============-->
<style name="Theme.Base.Amoled" parent="Theme.Base.Dark"> <style name="Theme.Base.Amoled" parent="Theme.Base.Dark">
<item name="colorPrimary">@color/colorAmoled</item> <item name="colorPrimary">@color/colorAmoledPrimary</item>
<item name="colorPrimaryDark">@color/colorAmoled</item> <item name="colorPrimaryDark">@color/colorAmoledPrimary</item>
<item name="android:colorBackground">@color/md_black_1000</item> <item name="android:colorBackground">@color/md_black_1000</item>
<!-- Custom Attributes--> <!-- Custom Attributes-->

View File

@ -7,9 +7,10 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0'
classpath 'com.github.zellius:android-shortcut-gradle-plugin:0.1.2' classpath 'com.github.zellius:android-shortcut-gradle-plugin:0.1.2'
classpath 'com.google.gms:google-services:3.2.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }

View File

@ -1,6 +1,6 @@
#Wed Oct 25 23:17:30 CEST 2017 #Thu Apr 05 09:21:32 CEST 2018
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip