Compare commits

..

13 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
27 changed files with 322 additions and 148 deletions

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

@ -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 35 versionCode 36
versionName "0.7.2" versionName "0.7.3"
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\"" buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""
@ -120,6 +120,8 @@ dependencies {
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

@ -49,8 +49,12 @@ class Mangachan : ParsedHttpSource() {
} }
} }
} }
is OrderBy -> { if (filter.state!!.ascending && filter.state!!.index == 0) { statusParam = false } } is OrderBy -> {
is Status -> status = arrayOf("", "all_done", "end", "ongoing", "new_ch")[filter.state] if (filter.state!!.ascending && filter.state!!.index == 0) {
statusParam = false
}
}
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,11 +429,13 @@ 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))
}
} }
} }

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

@ -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
} }
switchPreference { preferenceCategory {
key = Keys.cropBorders titleRes = R.string.pager_viewer
titleRes = R.string.pref_crop_borders
defaultValue = false switchPreference {
key = Keys.enableTransitions
titleRes = R.string.pref_page_transitions
defaultValue = true
}
switchPreference {
key = Keys.cropBorders
titleRes = R.string.pref_crop_borders
defaultValue = false
}
} }
switchPreference { preferenceCategory {
key = Keys.keepScreenOn titleRes = R.string.webtoon_viewer
titleRes = R.string.pref_keep_screen_on
defaultValue = true switchPreference {
key = Keys.cropBordersWebtoon
titleRes = R.string.pref_crop_borders
defaultValue = false
}
} }
preferenceCategory { preferenceCategory {
titleRes = R.string.pref_reader_navigation titleRes = R.string.pref_reader_navigation

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

@ -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,52 +13,49 @@
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"/>
<ProgressBar <FrameLayout
android:id="@+id/progress"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:layout_marginTop="32dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/divider1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/track_search"
tools:visibility="visible"/>
<ListView
android:id="@+id/track_search_list"
style="@style/Theme.Widget.CardView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="0dp"
android:layout_marginTop="40dp" android:layout_weight="1">
android:choiceMode="singleChoice"
android:clipToPadding="false" <ProgressBar
android:divider="@null" android:id="@+id/progress"
android:dividerHeight="10dp" style="?android:attr/progressBarStyle"
android:footerDividersEnabled="true" android:layout_width="wrap_content"
android:headerDividersEnabled="true" android:layout_height="wrap_content"
android:listSelector="?attr/selectable_list_drawable" android:layout_marginBottom="32dp"
android:paddingBottom="4dp" android:layout_marginTop="32dp"
android:paddingTop="4dp" android:layout_gravity="center"
android:scrollbars="none" android:visibility="invisible"
android:visibility="gone" tools:visibility="visible"/>
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" <ListView
app:layout_constraintTop_toTopOf="@+id/track_search" android:id="@+id/track_search_list"
tools:listitem="@layout/track_search_item" style="@style/Theme.Widget.CardView"
tools:visibility="visible"/> android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:choiceMode="singleChoice"
android:divider="@null"
android:dividerHeight="10dp"
android:footerDividersEnabled="true"
android:headerDividersEnabled="true"
android:listSelector="?attr/selectable_list_drawable"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:scrollbars="none"
android:visibility="invisible"
tools:listitem="@layout/track_search_item"
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,19 @@
<?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=""> <changelogversion versionName="v0.7.2" changeDate="">
<changelogtext>Fixed missing downloaded label in chapters screen.</changelogtext> <changelogtext>Fixed missing downloaded label in chapters screen.</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

@ -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

@ -7,9 +7,10 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.0' 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
} }