Skip to content

Commit e61dd37

Browse files
Actually load and show feeds on tv,
Fixed localization of strings with params, Publish extension library in jitpack, Load new sources with correct dispatchers
1 parent 314f74b commit e61dd37

File tree

24 files changed

+458
-265
lines changed

24 files changed

+458
-265
lines changed

app/src/main/java/com/mrboomdev/awery/app/App.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,7 @@ class App : Application() {
263263

264264
@JvmStatic
265265
fun i18n(@StringRes res: Int, vararg params: Any) =
266-
ContextCompat.getContextForLanguage(appContext).getString(res, params)
267-
268-
/*@JvmStatic
269-
fun i18n(@StringRes res: Int, vararg params: Any): String {
270-
return appContext.getString(res, *params)
271-
}*/
266+
ContextCompat.getContextForLanguage(appContext).getString(res, *params)
272267

273268
@JvmStatic
274269
@JvmOverloads

app/src/main/java/com/mrboomdev/awery/app/ExtensionsManager.kt

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ package com.mrboomdev.awery.app
22

33
import android.content.Context
44
import com.mrboomdev.awery.app.data.settings.NicePreferences.getPrefs
5+
import com.mrboomdev.awery.ext.data.CatalogFeed
6+
import com.mrboomdev.awery.ext.data.Setting
7+
import com.mrboomdev.awery.ext.data.Settings
58
import com.mrboomdev.awery.ext.source.Source
69
import com.mrboomdev.awery.ext.source.SourcesManager
710
import com.mrboomdev.awery.ext.util.Progress
811
import com.mrboomdev.awery.sources.yomi.YomiManager
912
import com.mrboomdev.awery.sources.yomi.aniyomi.AniyomiManager
1013
import com.mrboomdev.awery.sources.yomi.tachiyomi.TachiyomiManager
14+
import com.mrboomdev.awery.util.exceptions.ZeroResultsException
1115
import kotlinx.coroutines.async
1216
import kotlinx.coroutines.awaitAll
17+
import kotlinx.coroutines.channels.ProducerScope
1318
import kotlinx.coroutines.coroutineScope
1419
import kotlinx.coroutines.flow.channelFlow
1520
import kotlinx.coroutines.flow.collect
@@ -52,10 +57,80 @@ object ExtensionsManager {
5257
}
5358
}
5459

60+
fun List<CatalogFeed>.loadAll() = channelFlow {
61+
for(feed in this@loadAll) {
62+
loadFeed(feed)
63+
}
64+
}
65+
66+
private suspend fun ProducerScope<CatalogFeed.Loaded>.loadFeed(feed: CatalogFeed) {
67+
if(feed.managerId == "INTERNAL") {
68+
when(feed.feedId) {
69+
"AUTO_GENERATE" -> {
70+
val feeds = managers.map { it.getAll() }.flatten().map { it.getFeeds() }.flatten().shuffled()
71+
72+
for(gotFeed in feeds) {
73+
loadFeed(gotFeed)
74+
}
75+
}
76+
77+
"BOOKMARKS" -> {
78+
TODO()
79+
}
80+
}
81+
82+
return
83+
}
84+
85+
val manager = getManager(feed.managerId)
86+
87+
if(manager == null) {
88+
send(CatalogFeed.Loaded(
89+
feed = feed,
90+
throwable = ZeroResultsException("Source manager isn't installed! ${feed.managerId}")
91+
))
92+
93+
return
94+
}
95+
96+
val source = manager[feed.sourceId]
97+
98+
if(source == null) {
99+
send(CatalogFeed.Loaded(
100+
feed = feed,
101+
throwable = ZeroResultsException("Source isn't installed! ${feed.sourceId}")
102+
))
103+
104+
return
105+
}
106+
107+
try {
108+
send(CatalogFeed.Loaded(
109+
feed = feed,
110+
items = source.search(Source.Catalog.Media, Settings(
111+
object : Setting() {
112+
override val key: String = Source.FILTER_FEED
113+
override var value: Any? = feed
114+
},
115+
116+
object : Setting() {
117+
override val key: String = Source.FILTER_PAGE
118+
override var value: Any? = 0
119+
}
120+
))
121+
))
122+
} catch(t: Throwable) {
123+
send(CatalogFeed.Loaded(
124+
feed = feed,
125+
throwable = t
126+
))
127+
}
128+
}
129+
55130
fun getSource(globalId: String): Source? {
56131
return globalId.split(";;;").let {
57132
// Due to compatibility we have to trim all shit after :
58-
get(it[0])?.get(it[1].split(":")[0])
133+
getManager(it[0])?.get(it[1].split(":")[0])
59134
}
60135
}
61136

@@ -81,14 +156,14 @@ object ExtensionsManager {
81156
managers.add(manager)
82157
}
83158

84-
operator fun get(managerId: String): SourcesManager<*>? {
159+
fun getManager(managerId: String): SourcesManager<*>? {
85160
return managers.find {
86161
managerId == it.id
87162
}
88163
}
89164

90165
@Suppress("UNCHECKED_CAST")
91-
operator fun <T: SourcesManager<*>> get(clazz: KClass<T>): T? {
166+
fun <T: SourcesManager<*>> getManager(clazz: KClass<T>): T? {
92167
return managers.find {
93168
clazz == it::class
94169
} as T?
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.mrboomdev.awery.ext
2+
3+
import com.mrboomdev.awery.ext.source.Source
4+
import com.mrboomdev.awery.ext.util.Image
5+
import java.io.File
6+
7+
object ResourcesProvider {
8+
fun getFile(source: Source, path: String): File {
9+
throw UnsupportedOperationException("Stub1!")
10+
}
11+
12+
fun createImage(file: File): Image {
13+
throw UnsupportedOperationException("Stub1!")
14+
}
15+
}

app/src/main/java/com/mrboomdev/awery/extensions/data/CatalogFeed.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.mrboomdev.awery.generated.AwerySettings;
2121
import com.mrboomdev.awery.util.NiceUtils;
2222
import com.mrboomdev.awery.util.async.AsyncUtils;
23-
import com.mrboomdev.awery.util.exceptions.ExtensionNotInstalledException;
2423
import com.squareup.moshi.Json;
2524

2625
import java.io.Serial;
@@ -100,10 +99,6 @@ public String getProviderGlobalId() {
10099
return sourceManager + ";;;" + sourceId + ":" + extensionId;
101100
}
102101

103-
public ExtensionProvider getSourceProvider() throws ExtensionNotInstalledException {
104-
return ExtensionProvider.forGlobalId(sourceManager, extensionId, sourceId);
105-
}
106-
107102
/**
108103
* This method takes raw feeds with templating support and then returns list with processes feeds.
109104
* You can think about it as an preprocessor.
@@ -222,7 +217,7 @@ public boolean equals(@Nullable Object obj) {
222217

223218
@Override
224219
public int hashCode() {
225-
var hashCode = getProviderGlobalId().hashCode();
220+
var hashCode = getProviderGlobalId().hashCode();
226221

227222
if(displayMode != null) {
228223
hashCode += displayMode.hashCode();

app/src/main/java/com/mrboomdev/awery/sources/yomi/YomiManager.kt

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,36 +46,20 @@ abstract class YomiManager<S, T : YomiSource>(
4646
abstract val requiredFeature: String
4747
abstract val nsfwMeta: String
4848

49-
/**
50-
* It is marked as nullable, to be able to recalculate it's values,
51-
* but the returned value is always non-null.
52-
*/
53-
private var sourcesList: List<T>? = null
54-
get() {
55-
var it = field
56-
57-
if(field == null) {
58-
it = sources.values.toList()
59-
field = it
60-
}
61-
62-
return it
63-
}
64-
6549
override fun get(id: String): T {
6650
return sources[id] ?: throw NoSuchElementException(id)
6751
}
6852

6953
override fun getAll(): List<T> {
70-
return sourcesList!!
54+
return sources.values.toList()
7155
}
7256

7357
override suspend fun load(id: String) {
74-
createSource(id, true)
58+
sources[id] = createSource(id, true)
7559
}
7660

7761
override suspend fun unload(id: String) {
78-
createSource(id, false)
62+
sources[id] = createSource(id, false)
7963
}
8064

8165
private fun getPackages(context: Context): List<PackageInfo> {
@@ -101,7 +85,7 @@ abstract class YomiManager<S, T : YomiSource>(
10185
coroutineScope {
10286
getPackages(context).map { pkg ->
10387
async {
104-
createSource(pkg.packageName, isEnabled(pkg.packageName))
88+
sources[pkg.packageName] = createSource(pkg.packageName, isEnabled(pkg.packageName))
10589
progress.increment()
10690
send(progress)
10791
}

app/src/main/java/com/mrboomdev/awery/sources/yomi/YomiSource.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import com.mrboomdev.awery.ext.source.Source
88
abstract class YomiSource(
99
val packageInfo: PackageInfo
1010
): Source() {
11-
override val id = packageInfo.packageName
11+
final override val id = packageInfo.packageName
1212
abstract val feeds: CatalogSearchResults<CatalogFeed>?
1313

1414
final override suspend fun getFeeds(): CatalogSearchResults<CatalogFeed> {

app/src/main/java/com/mrboomdev/awery/sources/yomi/aniyomi/AniyomiSource.kt

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package com.mrboomdev.awery.sources.yomi.aniyomi
22

33
import android.content.pm.PackageInfo
44
import com.mrboomdev.awery.ext.constants.AweryFeature
5-
import com.mrboomdev.awery.ext.constants.AweryFilters
65
import com.mrboomdev.awery.ext.data.CatalogFeed
76
import com.mrboomdev.awery.ext.data.CatalogMedia
87
import com.mrboomdev.awery.ext.data.CatalogSearchResults
98
import com.mrboomdev.awery.ext.data.Settings
9+
import com.mrboomdev.awery.ext.source.Source
1010
import com.mrboomdev.awery.sources.yomi.YomiSource
1111
import com.mrboomdev.awery.util.extensions.mapOfNotNull
1212
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
@@ -15,6 +15,8 @@ import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
1515
import eu.kanade.tachiyomi.animesource.model.AnimesPage
1616
import eu.kanade.tachiyomi.animesource.model.SAnime
1717
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
18+
import kotlinx.coroutines.Dispatchers
19+
import kotlinx.coroutines.withContext
1820

1921
abstract class AniyomiSource(
2022
packageInfo: PackageInfo,
@@ -23,10 +25,19 @@ abstract class AniyomiSource(
2325

2426
override val feeds = if(source is AnimeCatalogueSource) {
2527
CatalogSearchResults(listOfNotNull(
26-
CatalogFeed(FEED_POPULAR, "Popular in ${source.name}"),
28+
CatalogFeed(
29+
managerId = AniyomiManager.ID,
30+
sourceId = id,
31+
feedId = FEED_POPULAR,
32+
title = "Popular in ${source.name}"
33+
),
2734

28-
if(!source.supportsLatest) null
29-
else CatalogFeed(FEED_LATEST, "Latest in ${source.name}")
35+
if(!source.supportsLatest) null else CatalogFeed(
36+
managerId = AniyomiManager.ID,
37+
sourceId = id,
38+
feedId = FEED_LATEST,
39+
title = "Latest in ${source.name}"
40+
)
3041
))
3142
} else null
3243

@@ -42,56 +53,63 @@ abstract class AniyomiSource(
4253
}.toTypedArray()
4354

4455
private suspend fun getAnimesPage(filters: Settings): AnimesPage {
45-
if(source is AnimeCatalogueSource) {
46-
val feed = filters[AweryFilters.FEED]?.value as? String
47-
val query = filters[AweryFilters.QUERY]?.value as? String ?: ""
48-
val page = filters[AweryFilters.PAGE]?.value as? Int ?: 0
56+
return withContext(Dispatchers.IO) {
57+
if(source is AnimeCatalogueSource) {
58+
val feed = filters[FILTER_FEED]?.value as? String
59+
val query = filters[FILTER_QUERY]?.value as? String ?: ""
60+
val page = filters[FILTER_PAGE]?.value as? Int ?: 0
4961

50-
return when(feed) {
51-
FEED_POPULAR -> source.getPopularAnime(page)
52-
FEED_LATEST -> source.getLatestUpdates(page)
62+
return@withContext when(feed) {
63+
FEED_POPULAR -> source.getPopularAnime(page)
64+
FEED_LATEST -> source.getLatestUpdates(page)
5365

54-
else -> {
55-
// TODO: Apply filters
56-
source.getSearchAnime(page, query, source.getFilterList())
66+
else -> {
67+
// TODO: Apply filters
68+
source.getSearchAnime(page, query, source.getFilterList())
69+
}
5770
}
5871
}
59-
}
6072

61-
throw UnsupportedOperationException("This source doesn't support browsing!")
73+
throw UnsupportedOperationException("This source doesn't support browsing!")
74+
}
6275
}
6376

64-
override suspend fun searchMedia(filters: Settings): CatalogSearchResults<CatalogMedia> {
65-
return getAnimesPage(filters).let { page ->
66-
CatalogSearchResults(page.animes.map { anime ->
67-
CatalogMedia(
68-
globalId = "${AniyomiManager.ID};;;$id;;;${anime.url}",
69-
titles = arrayOf(anime.title),
70-
description = anime.description,
71-
poster = anime.thumbnail_url,
72-
extra = anime.url,
73-
type = CatalogMedia.Type.TV,
74-
75-
genres = anime.genre?.split(", ")?.toTypedArray(),
76-
77-
url = if(source is AnimeHttpSource) {
78-
concatLink(source.baseUrl, anime.url)
79-
} else null,
80-
81-
status = when(anime.status) {
82-
SAnime.COMPLETED, SAnime.PUBLISHING_FINISHED -> CatalogMedia.Status.COMPLETED
83-
SAnime.ON_HIATUS -> CatalogMedia.Status.PAUSED
84-
SAnime.ONGOING -> CatalogMedia.Status.ONGOING
85-
SAnime.CANCELLED -> CatalogMedia.Status.CANCELLED
86-
else -> null
87-
},
88-
89-
authors = mapOfNotNull(
90-
"Artist" to anime.artist,
91-
"Author" to anime.author
77+
@Suppress("UNCHECKED_CAST")
78+
override suspend fun <E, T : Catalog<E>> search(catalog: T, filters: Settings): CatalogSearchResults<E> {
79+
return when(catalog) {
80+
is Catalog.Media -> getAnimesPage(filters).let { page ->
81+
CatalogSearchResults(page.animes.map { anime ->
82+
CatalogMedia(
83+
globalId = "${AniyomiManager.ID};;;$id;;;${anime.url}",
84+
titles = arrayOf(anime.title),
85+
description = anime.description,
86+
poster = anime.thumbnail_url,
87+
extra = anime.url,
88+
type = CatalogMedia.Type.TV,
89+
90+
genres = anime.genre?.split(", ")?.toTypedArray(),
91+
92+
url = if(source is AnimeHttpSource) {
93+
concatLink(source.baseUrl, anime.url)
94+
} else null,
95+
96+
status = when(anime.status) {
97+
SAnime.COMPLETED, SAnime.PUBLISHING_FINISHED -> CatalogMedia.Status.COMPLETED
98+
SAnime.ON_HIATUS -> CatalogMedia.Status.PAUSED
99+
SAnime.ONGOING -> CatalogMedia.Status.ONGOING
100+
SAnime.CANCELLED -> CatalogMedia.Status.CANCELLED
101+
else -> null
102+
},
103+
104+
authors = mapOfNotNull(
105+
"Artist" to anime.artist,
106+
"Author" to anime.author
107+
)
92108
)
93-
)
94-
}, page.hasNextPage)
109+
}, page.hasNextPage)
110+
} as CatalogSearchResults<E>
111+
112+
else -> throw UnsupportedOperationException("Unsupported type!")
95113
}
96114
}
97115
}

0 commit comments

Comments
 (0)