From d6136765a7121223025a32f0c303d65a5cd31308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Fri, 20 Jun 2025 21:18:57 -0400 Subject: [PATCH 1/8] News provider config --- .../commons/provider/CaSTOProvider.java | 8 ++++ .../provider/ContentProviderConstants.java | 2 + .../commons/provider/InstagramNewsProvider.kt | 4 ++ .../commons/provider/NewsProvider.java | 12 ++++++ .../provider/NewsProviderContract.java | 26 +++++++++++++ .../commons/provider/RSSNewsProvider.java | 7 ++++ .../commons/provider/TwitterNewsProvider.kt | 39 +++++++++++++------ .../provider/WinnipegTransitProvider.java | 7 ++++ .../commons/provider/YouTubeNewsProvider.kt | 23 ++++++++++- .../commons/provider/config/ProviderConfig.kt | 3 ++ .../config/news/DefaultNewsProviderConfig.kt | 5 +++ .../provider/config/news/NewsFeedConfig.kt | 30 ++++++++++++++ .../config/news/NewsProviderConfig.kt | 17 ++++++++ .../news/twitter/TwitterNewsFeedConfig.kt | 34 ++++++++++++++++ .../news/twitter/TwitterNewsProviderConfig.kt | 7 ++++ .../news/youtube/YouTubeNewsFeedConfig.kt | 38 ++++++++++++++++++ .../news/youtube/YouTubeNewsProviderConfig.kt | 7 ++++ 17 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/ProviderConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/NewsProviderConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsProviderConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsProviderConfig.kt diff --git a/src/main/java/org/mtransit/android/commons/provider/CaSTOProvider.java b/src/main/java/org/mtransit/android/commons/provider/CaSTOProvider.java index 9313f550..0b1a5bab 100644 --- a/src/main/java/org/mtransit/android/commons/provider/CaSTOProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/CaSTOProvider.java @@ -29,6 +29,8 @@ import org.mtransit.android.commons.UriUtils; import org.mtransit.android.commons.data.News; import org.mtransit.android.commons.helpers.MTDefaultHandler; +import org.mtransit.android.commons.provider.config.news.DefaultNewsProviderConfig; +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; import org.mtransit.android.commons.provider.news.NewsTextFormatter; import org.mtransit.commons.SourceUtils; import org.xml.sax.Attributes; @@ -160,6 +162,12 @@ private static String getNEWS_TARGET_AUTHORITY(@NonNull Context context) { return newsTargetAuthority; } + @NonNull + @Override + public NewsProviderConfig getNewsConfig() { + return new DefaultNewsProviderConfig(); + } + /** * Override if multiple {@link CaSTOProvider} implementations in same app. */ diff --git a/src/main/java/org/mtransit/android/commons/provider/ContentProviderConstants.java b/src/main/java/org/mtransit/android/commons/provider/ContentProviderConstants.java index 1609101f..b163a0ca 100644 --- a/src/main/java/org/mtransit/android/commons/provider/ContentProviderConstants.java +++ b/src/main/java/org/mtransit/android/commons/provider/ContentProviderConstants.java @@ -39,5 +39,7 @@ public final class ContentProviderConstants { // public static final int NEWS = 115; // + public static final int CONFIG = 555; + // public static final int ALL = 999; } diff --git a/src/main/java/org/mtransit/android/commons/provider/InstagramNewsProvider.kt b/src/main/java/org/mtransit/android/commons/provider/InstagramNewsProvider.kt index 92f3860a..0da07096 100644 --- a/src/main/java/org/mtransit/android/commons/provider/InstagramNewsProvider.kt +++ b/src/main/java/org/mtransit/android/commons/provider/InstagramNewsProvider.kt @@ -24,6 +24,7 @@ import org.mtransit.android.commons.data.News import org.mtransit.android.commons.provider.InstagramNewsProvider.InstagramApi.JEdgeOwnerToTimelineMediaNode import org.mtransit.android.commons.provider.InstagramNewsProvider.InstagramApi.JProfileUser import org.mtransit.android.commons.provider.agency.AgencyUtils +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig import retrofit2.Call import retrofit2.http.GET import retrofit2.http.Path @@ -138,6 +139,9 @@ class InstagramNewsProvider : NewsProvider() { ) } + override fun getNewsConfig(): NewsProviderConfig { + } + override fun getLogTag() = LOG_TAG override fun getURI_MATCHER() = _uriMatcher diff --git a/src/main/java/org/mtransit/android/commons/provider/NewsProvider.java b/src/main/java/org/mtransit/android/commons/provider/NewsProvider.java index dfdf96cd..2838ee32 100644 --- a/src/main/java/org/mtransit/android/commons/provider/NewsProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/NewsProvider.java @@ -24,6 +24,7 @@ import org.mtransit.android.commons.StringUtils; import org.mtransit.android.commons.TimeUtils; import org.mtransit.android.commons.data.News; +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; import org.mtransit.commons.CollectionUtils; import org.mtransit.commons.sql.SQLCreateBuilder; import org.mtransit.commons.sql.SQLInsertBuilder; @@ -52,6 +53,7 @@ public static UriMatcher getNewUriMatcher(@NonNull String authority) { public static void append(@NonNull UriMatcher uriMatcher, @NonNull String authority) { uriMatcher.addURI(authority, NewsProviderContract.PING_PATH, ContentProviderConstants.PING); uriMatcher.addURI(authority, NewsProviderContract.NEWS_PATH, ContentProviderConstants.NEWS); + uriMatcher.addURI(authority, NewsProviderContract.CONFIG_PATH, ContentProviderConstants.CONFIG); } @Nullable @@ -142,11 +144,19 @@ public static Cursor queryS(@NonNull NewsProviderContract provider, @NonNull Uri return ContentProviderConstants.EMPTY_CURSOR; // empty cursor = processed case ContentProviderConstants.NEWS: return getNews(provider, selection); + case ContentProviderConstants.CONFIG: + return getNewsConfig(provider); default: return null; // not processed } } + @Nullable + private static Cursor getNewsConfig(@NonNull NewsProviderContract provider) { + final NewsProviderConfig providerNewsConfig = provider.getNewsConfig(); + return providerNewsConfig.toCursor(); + } + @Nullable private static Cursor getNews(@NonNull NewsProviderContract provider, @Nullable String selection) { NewsProviderContract.Filter newsFilter = NewsProviderContract.Filter.fromJSONString(selection); @@ -318,7 +328,9 @@ public String getTypeMT(@NonNull Uri uri) { @Nullable public static String getTypeS(@NonNull NewsProviderContract provider, @NonNull Uri uri) { switch (provider.getURI_MATCHER().match(uri)) { + case ContentProviderConstants.PING: case ContentProviderConstants.NEWS: + case ContentProviderConstants.CONFIG: return StringUtils.EMPTY; // empty string = processed default: return null; // not processed diff --git a/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java b/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java index b9ef8f8a..e4d63f05 100644 --- a/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java +++ b/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java @@ -19,6 +19,7 @@ import org.mtransit.android.commons.data.News; import org.mtransit.android.commons.data.POI; import org.mtransit.android.commons.data.RouteTripStop; +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; import org.mtransit.commons.CollectionUtils; import java.util.ArrayList; @@ -30,6 +31,7 @@ public interface NewsProviderContract extends ProviderContract { String NEWS_PATH = "news"; + String CONFIG_PATH = "config"; // TODO move to ProviderContract once implemented everywhere boolean REMOVE_IMAGE_FROM_TEXT = false; // TODO later @@ -74,6 +76,9 @@ public interface NewsProviderContract extends ProviderContract { @NonNull Collection getNewsLanguages(); + @NonNull + NewsProviderConfig getNewsConfig(); + interface Columns { String T_NEWS_K_ID = BaseColumns._ID; String T_NEWS_K_AUTHORITY_META = "authority"; @@ -133,6 +138,27 @@ interface Columns { Columns.T_NEWS_K_IMAGE_URL_INDEX + 9, // }; + interface FeedConfigColumns { + String T_NEWS_FEED_CONFIG_K_TARGET = "target"; + String T_NEWS_FEED_CONFIG_K_LANG = "lang"; + String T_NEWS_FEED_CONFIG_K_COLOR = "color"; + String T_NEWS_FEED_CONFIG_K_SEVERITY = "severity"; + String T_NEWS_FEED_CONFIG_K_NOTEWORTHY = "noteworthy"; + + String T_NEWS_FEED_CONFIG_K_EXTRA = "extra"; + + } + + String[] PROJECTION_NEWS_FEED_CONFIG = new String[]{ + FeedConfigColumns.T_NEWS_FEED_CONFIG_K_TARGET, + FeedConfigColumns.T_NEWS_FEED_CONFIG_K_LANG, + FeedConfigColumns.T_NEWS_FEED_CONFIG_K_COLOR, + FeedConfigColumns.T_NEWS_FEED_CONFIG_K_SEVERITY, + FeedConfigColumns.T_NEWS_FEED_CONFIG_K_NOTEWORTHY, + + FeedConfigColumns.T_NEWS_FEED_CONFIG_K_EXTRA, + }; + @SuppressWarnings("WeakerAccess") class Filter implements MTLog.Loggable { diff --git a/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java b/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java index 9880e6b4..156c3fe6 100644 --- a/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java @@ -27,6 +27,8 @@ import org.mtransit.android.commons.UriUtils; import org.mtransit.android.commons.data.News; import org.mtransit.android.commons.helpers.MTDefaultHandler; +import org.mtransit.android.commons.provider.config.news.DefaultNewsProviderConfig; +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; import org.mtransit.android.commons.provider.news.NewsTextFormatter; import org.mtransit.android.commons.provider.news.rss.RssNewProviderUtils; import org.mtransit.commons.CleanUtils; @@ -234,6 +236,11 @@ private static java.util.List getFEEDS_LABEL(@NonNull Context context) { return feedsLabel; } + @NonNull + @Override + public NewsProviderConfig getNewsConfig() { + } + @NonNull @Override public UriMatcher getURI_MATCHER() { diff --git a/src/main/java/org/mtransit/android/commons/provider/TwitterNewsProvider.kt b/src/main/java/org/mtransit/android/commons/provider/TwitterNewsProvider.kt index 550953c2..e4b4c5ff 100644 --- a/src/main/java/org/mtransit/android/commons/provider/TwitterNewsProvider.kt +++ b/src/main/java/org/mtransit/android/commons/provider/TwitterNewsProvider.kt @@ -33,6 +33,8 @@ import org.mtransit.android.commons.TimeUtils import org.mtransit.android.commons.UriUtils import org.mtransit.android.commons.data.News import org.mtransit.android.commons.provider.agency.AgencyUtils +import org.mtransit.android.commons.provider.config.news.twitter.TwitterNewsFeedConfig +import org.mtransit.android.commons.provider.config.news.twitter.TwitterNewsProviderConfig import org.mtransit.android.commons.provider.news.NewsTextFormatter import org.mtransit.android.commons.provider.news.twitter.TwitterNewsDbHelper import org.mtransit.android.commons.provider.news.twitter.TwitterStorage @@ -203,6 +205,21 @@ class TwitterNewsProvider : NewsProvider() { ) } + override fun getNewsConfig() = TwitterNewsProviderConfig( + newsFeedConfigs = _userNames.mapIndexed { i, username -> + TwitterNewsFeedConfig( + username = username, + userId = _userNamesId.getOrNull(i), // optional (saved 1 request) + lang = _userNamesLang.getOrNull(i) ?: LocaleUtils.UNKNOWN, + color = _userNamesColors.getOrNull(i) ?: _color.takeIf { it.isNotBlank() }, // optional (fallback: agency color) + target = _userNamesTarget.getOrNull(i)?.takeIf { it.isNotBlank() } + ?: _targetAuthority.takeIf { it.isNotBlank() }, // optional (fallback: agency UUID) + severity = _userNamesSeverity.getOrNull(i) ?: TwitterNewsFeedConfig.SEVERITY_DEFAULT, + noteworthy = _userNamesNoteworthy.getOrNull(i) ?: TwitterNewsFeedConfig.NOTEWORTHY_DEFAULT, + ) + } + ) + override fun getLogTag() = LOG_TAG override fun getURI_MATCHER() = _uriMatcher @@ -395,7 +412,7 @@ class TwitterNewsProvider : NewsProvider() { val newNews = ArrayList() val maxValidityInMs = newsMaxValidityInMs val authority = _authority - for ((i, userName) in _userNames.withIndex()) { + _userNames.forEachIndexed { i, userName -> loadUserTimeline( context, twitterApi, @@ -495,10 +512,16 @@ class TwitterNewsProvider : NewsProvider() { val tweetsResp = response.data val tweetsRespIncludedExpansions = response.includes var newSinceId: String? = null + val colorString = _userNamesColors.getOrNull(i) + ?: _color.takeIf { it.isNotBlank() } + ?: AgencyUtils.getAgencyColor(context) + ?: ColorUtils.BLACK + .also { + MTLog.w(this, "No color found for '$username'! (used fallback)") + } tweetsResp ?.forEach { tweet -> readNews( - context, tweet, tweetsRespIncludedExpansions, authority, @@ -509,7 +532,8 @@ class TwitterNewsProvider : NewsProvider() { targetUUID, userId, username, - userLang + userLang, + colorString, )?.apply { if (newSinceId == null) { newSinceId = tweet.id @@ -531,7 +555,6 @@ class TwitterNewsProvider : NewsProvider() { @RequiresApi(Build.VERSION_CODES.O) private fun readNews( - context: Context, tweet: Tweet, includedExpansions: Expansions?, authority: String, @@ -543,6 +566,7 @@ class TwitterNewsProvider : NewsProvider() { userId: String, userName: String, userLang: String, + colorString: String, ): News? { if (tweet.inReplyToUserId != null && tweet.inReplyToUserId != userId) { MTLog.d(this, "readNews() > SKIP (in reply to screen name: '%s').", tweet.inReplyToUserId) @@ -565,13 +589,6 @@ class TwitterNewsProvider : NewsProvider() { val lang: String = getLang(tweet, userLang) val createdAtInMs = tweet.createdAt?.toInstant()?.toEpochMilli() ?: newLastUpdateInMs // should never happen - val colorString = _userNamesColors.getOrNull(_userNames.indexOf(authorUserName)) - ?: _color.takeIf { it.isNotBlank() } - ?: AgencyUtils.getAgencyColor(context) - ?: ColorUtils.BLACK - .also { - MTLog.w(this, "No color found for '$userName'! (used fallback)") - } return News( null, authority, diff --git a/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java b/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java index 2fcae368..440ce6df 100644 --- a/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java @@ -39,6 +39,8 @@ import org.mtransit.android.commons.data.RouteTripStop; import org.mtransit.android.commons.data.Schedule; import org.mtransit.android.commons.data.Trip; +import org.mtransit.android.commons.provider.config.news.DefaultNewsProviderConfig; +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; import org.mtransit.commons.CleanUtils; import org.mtransit.commons.FeatureFlags; import org.mtransit.commons.SourceUtils; @@ -181,6 +183,11 @@ private static String getNEWS_TARGET_AUTHORITY(@NonNull Context context) { return newsTargetAuthority; } + @NonNull + @Override + public NewsProviderConfig getNewsConfig() { + } + private static final long WEB_SERVICE_STATUS_MAX_VALIDITY_IN_MS = TimeUnit.HOURS.toMillis(1L); private static final long WEB_SERVICE_STATUS_VALIDITY_IN_MS = TimeUnit.MINUTES.toMillis(10L); private static final long WEB_SERVICE_STATUS_VALIDITY_IN_FOCUS_IN_MS = TimeUnit.MINUTES.toMillis(1L); diff --git a/src/main/java/org/mtransit/android/commons/provider/YouTubeNewsProvider.kt b/src/main/java/org/mtransit/android/commons/provider/YouTubeNewsProvider.kt index aeca47db..197e35f0 100644 --- a/src/main/java/org/mtransit/android/commons/provider/YouTubeNewsProvider.kt +++ b/src/main/java/org/mtransit/android/commons/provider/YouTubeNewsProvider.kt @@ -22,6 +22,8 @@ import org.mtransit.android.commons.UriUtils import org.mtransit.android.commons.data.News import org.mtransit.android.commons.linkifyAllURLs import org.mtransit.android.commons.provider.agency.AgencyUtils +import org.mtransit.android.commons.provider.config.news.youtube.YouTubeNewsFeedConfig +import org.mtransit.android.commons.provider.config.news.youtube.YouTubeNewsProviderConfig import org.mtransit.android.commons.provider.news.NewsTextFormatter import org.mtransit.android.commons.provider.news.youtube.YouTubeNewsDbHelper import org.mtransit.android.commons.provider.news.youtube.YouTubeStorage @@ -164,6 +166,22 @@ class YouTubeNewsProvider : NewsProvider() { ) } + override fun getNewsConfig() = YouTubeNewsProviderConfig( + newsFeedConfigs = _authorUrls.mapIndexed { i, authorUrl -> + YouTubeNewsFeedConfig( + authorUrl = authorUrl, + username = _userNames.getOrNull(i), + userHandle = _userNamesHandles.getOrNull(i), + channelId = _userNamesChannelsId.getOrNull(i), + lang = _userNamesLang.getOrNull(i) ?: LocaleUtils.UNKNOWN, + color = _userNamesColors.getOrNull(i), + target = _userNamesTarget.getOrNull(i), + severity = _userNamesSeverity.getOrNull(i) ?: YouTubeNewsFeedConfig.SEVERITY_DEFAULT, + noteworthy = _userNamesNoteworthy.getOrNull(i) ?: YouTubeNewsFeedConfig.NOTEWORTHY_DEFAULT, + ) + } + ) + override fun getLogTag() = LOG_TAG override fun getURI_MATCHER() = _uriMatcher @@ -346,7 +364,7 @@ class YouTubeNewsProvider : NewsProvider() { val newNews = ArrayList() val maxValidityInMs = newsMaxValidityInMs val authority = _authority - for ((i, authorUrl) in _authorUrls.withIndex()) { + _authorUrls.forEachIndexed { i, authorUrl -> loadUserUploadsPlaylist( context, youtubeService, @@ -393,10 +411,11 @@ class YouTubeNewsProvider : NewsProvider() { .list(CHANNEL_PARTS) .apply { when { + // from author URL username?.isNotBlank() == true -> setForUsername(username) userHandle?.isNotBlank() == true -> setForHandle(userHandle) channelId?.isNotBlank() == true -> setId(listOf(channelId)) - + // provided in config _userNames.getOrNull(i)?.isNotBlank() == true -> setForUsername(_userNames[i]) _userNamesHandles.getOrNull(i)?.isNotBlank() == true -> setForHandle(_userNamesHandles[i]) _userNamesChannelsId.getOrNull(i)?.isNotBlank() == true -> setId(listOf(_userNamesChannelsId[i])) diff --git a/src/main/java/org/mtransit/android/commons/provider/config/ProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/ProviderConfig.kt new file mode 100644 index 00000000..88942dbd --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/ProviderConfig.kt @@ -0,0 +1,3 @@ +package org.mtransit.android.commons.provider.config + +interface ProviderConfig diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt new file mode 100644 index 00000000..78ab867c --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt @@ -0,0 +1,5 @@ +package org.mtransit.android.commons.provider.config.news + +data class DefaultNewsProviderConfig @JvmOverloads constructor( + override val newsFeedConfigs: List = emptyList() +) : NewsProviderConfig diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt new file mode 100644 index 00000000..1f21fdef --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt @@ -0,0 +1,30 @@ +package org.mtransit.android.commons.provider.config.news + +import org.mtransit.android.commons.LocaleUtils + +interface NewsFeedConfig { + val target: String? get() = null // target the entire agency + val lang: String get() = LocaleUtils.UNKNOWN // show all + val color: String? get() = null // same as agency (target?) color + val severity: Int get() = 1 // news_provider_severity_info_unknown + val noteworthy: Long get() = 86_400_000L // news_provider_noteworthy_info // 1 days + + /** + * See [org.mtransit.android.commons.provider.NewsProviderContract.FeedConfigColumns] + * See [org.mtransit.android.commons.provider.NewsProviderContract.PROJECTION_NEWS_FEED_CONFIG] + */ + fun toCursorRow(): Array { + return makeCursorRow() + } + + fun makeCursorRow(extra: String? = null): Array { + return arrayOf( + target.orEmpty(), + lang, + color.orEmpty(), + severity, + noteworthy, + extra.orEmpty(), + ) + } +} \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsProviderConfig.kt new file mode 100644 index 00000000..fe0ed3e0 --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsProviderConfig.kt @@ -0,0 +1,17 @@ +package org.mtransit.android.commons.provider.config.news + +import android.database.Cursor +import android.database.MatrixCursor +import org.mtransit.android.commons.provider.NewsProviderContract +import org.mtransit.android.commons.provider.config.ProviderConfig + +interface NewsProviderConfig : ProviderConfig { + val newsFeedConfigs: List + + fun toCursor(): Cursor = + MatrixCursor(NewsProviderContract.PROJECTION_NEWS_FEED_CONFIG).apply { + newsFeedConfigs.forEach { + addRow(it.toCursorRow()) + } + } +} \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt new file mode 100644 index 00000000..33cf6392 --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt @@ -0,0 +1,34 @@ +package org.mtransit.android.commons.provider.config.news.twitter + +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import org.mtransit.android.commons.LocaleUtils +import org.mtransit.android.commons.provider.config.news.NewsFeedConfig + +data class TwitterNewsFeedConfig( + val username: String, + val userId: String? = null, // optional (saved 1 call to Twitter API) + override val target: String? = null, + override val lang: String = LocaleUtils.UNKNOWN, // TODO ? LocaleUtils.MULTIPLE, // detect lang from Twitter API + override val color: String? = null, + override val severity: Int = SEVERITY_DEFAULT, + override val noteworthy: Long = NOTEWORTHY_DEFAULT, +) : NewsFeedConfig { + + companion object { + const val SEVERITY_DEFAULT = 2 // news_provider_severity_info_agency + const val NOTEWORTHY_DEFAULT = 10_800_000L // news_provider_noteworthy_warning // 3 hours + } + + override fun toCursorRow(): Array { + return makeCursorRow( + extra = Json.encodeToString( + buildJsonObject { + put("username", username) + put("userId", userId) + } + ) + ) + } +} diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsProviderConfig.kt new file mode 100644 index 00000000..f94bd445 --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsProviderConfig.kt @@ -0,0 +1,7 @@ +package org.mtransit.android.commons.provider.config.news.twitter + +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig + +data class TwitterNewsProviderConfig( + override val newsFeedConfigs: List +) : NewsProviderConfig \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt new file mode 100644 index 00000000..0059fa04 --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt @@ -0,0 +1,38 @@ +package org.mtransit.android.commons.provider.config.news.youtube + +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.put +import kotlinx.serialization.json.buildJsonObject +import org.mtransit.android.commons.LocaleUtils +import org.mtransit.android.commons.provider.config.news.NewsFeedConfig + +data class YouTubeNewsFeedConfig( + val authorUrl: String, // can extract "username OR @userHandle or channel ID" from url + val username: String? = null, // optional (username OR @userHandle or channel ID) + val userHandle: String? = null, // optional (username OR @userHandle or channel ID) + val channelId: String? = null, // optional (username OR @userHandle or channel ID) + override val target: String? = null, // default to agency + override val color: String? = null, // defaults to agency + override val lang: String = LocaleUtils.UNKNOWN, // show all + override val severity: Int = SEVERITY_DEFAULT, + override val noteworthy: Long = NOTEWORTHY_DEFAULT, +) : NewsFeedConfig { + + companion object { + const val SEVERITY_DEFAULT = 2 // news_provider_severity_info_agency + const val NOTEWORTHY_DEFAULT = 604_800_000L // news_provider_noteworthy_long_term // 1 week + } + + override fun toCursorRow(): Array { + return makeCursorRow( + extra = Json.encodeToString( + buildJsonObject { + put("authorUrl", authorUrl) + put("username", username) + put("userHandle", userHandle) + put("channelId", channelId) + } + ) + ) + } +} diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsProviderConfig.kt new file mode 100644 index 00000000..284e6f87 --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsProviderConfig.kt @@ -0,0 +1,7 @@ +package org.mtransit.android.commons.provider.config.news.youtube + +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig + +data class YouTubeNewsProviderConfig( + override val newsFeedConfigs: List +) : NewsProviderConfig \ No newline at end of file From d546423f13b044b5a8d7d8f53c895e28561ec89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Fri, 20 Jun 2025 21:24:12 -0400 Subject: [PATCH 2/8] cleanup --- .../provider/config/news/NewsFeedConfig.kt | 18 ++++++++---------- .../news/twitter/TwitterNewsFeedConfig.kt | 2 +- .../news/youtube/YouTubeNewsFeedConfig.kt | 6 +++--- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt index 1f21fdef..cc0e1923 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt @@ -17,14 +17,12 @@ interface NewsFeedConfig { return makeCursorRow() } - fun makeCursorRow(extra: String? = null): Array { - return arrayOf( - target.orEmpty(), - lang, - color.orEmpty(), - severity, - noteworthy, - extra.orEmpty(), - ) - } + fun makeCursorRow(extra: String? = null) = arrayOf( + target.orEmpty(), + lang, + color.orEmpty(), + severity, + noteworthy, + extra.orEmpty(), + ) } \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt index 33cf6392..73c804f9 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt @@ -26,7 +26,7 @@ data class TwitterNewsFeedConfig( extra = Json.encodeToString( buildJsonObject { put("username", username) - put("userId", userId) + userId?.let { put("userId", it) } } ) ) diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt index 0059fa04..bb34cf28 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt @@ -28,9 +28,9 @@ data class YouTubeNewsFeedConfig( extra = Json.encodeToString( buildJsonObject { put("authorUrl", authorUrl) - put("username", username) - put("userHandle", userHandle) - put("channelId", channelId) + username?.let { put("username", it) } + userHandle?.let { put("userHandle", it) } + channelId?.let { put("channelId", it) } } ) ) From 06443db895a8597899df78269c5a70a601421127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Fri, 20 Jun 2025 21:25:54 -0400 Subject: [PATCH 3/8] Winnipeg --- .../android/commons/provider/WinnipegTransitProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java b/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java index 440ce6df..81aceffe 100644 --- a/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java @@ -186,6 +186,7 @@ private static String getNEWS_TARGET_AUTHORITY(@NonNull Context context) { @NonNull @Override public NewsProviderConfig getNewsConfig() { + return new DefaultNewsProviderConfig(); } private static final long WEB_SERVICE_STATUS_MAX_VALIDITY_IN_MS = TimeUnit.HOURS.toMillis(1L); From bb38aa97e793a800942f06a5e7f51116480cbd6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Fri, 20 Jun 2025 21:32:43 -0400 Subject: [PATCH 4/8] Instagram --- .../commons/provider/InstagramNewsProvider.kt | 20 +++++++++--- .../news/instagram/InstagramNewsFeedConfig.kt | 32 +++++++++++++++++++ .../instagram/InstagramNewsProviderConfig.kt | 7 ++++ 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsProviderConfig.kt diff --git a/src/main/java/org/mtransit/android/commons/provider/InstagramNewsProvider.kt b/src/main/java/org/mtransit/android/commons/provider/InstagramNewsProvider.kt index 0da07096..bbd07bc0 100644 --- a/src/main/java/org/mtransit/android/commons/provider/InstagramNewsProvider.kt +++ b/src/main/java/org/mtransit/android/commons/provider/InstagramNewsProvider.kt @@ -24,7 +24,8 @@ import org.mtransit.android.commons.data.News import org.mtransit.android.commons.provider.InstagramNewsProvider.InstagramApi.JEdgeOwnerToTimelineMediaNode import org.mtransit.android.commons.provider.InstagramNewsProvider.InstagramApi.JProfileUser import org.mtransit.android.commons.provider.agency.AgencyUtils -import org.mtransit.android.commons.provider.config.news.NewsProviderConfig +import org.mtransit.android.commons.provider.config.news.instagram.InstagramNewsFeedConfig +import org.mtransit.android.commons.provider.config.news.instagram.InstagramNewsProviderConfig import retrofit2.Call import retrofit2.http.GET import retrofit2.http.Path @@ -139,8 +140,19 @@ class InstagramNewsProvider : NewsProvider() { ) } - override fun getNewsConfig(): NewsProviderConfig { - } + override fun getNewsConfig() = InstagramNewsProviderConfig( + newsFeedConfigs = _userNames.mapIndexed { i, username -> + InstagramNewsFeedConfig( + username = username, + lang = _userNamesLang.getOrNull(i) ?: LocaleUtils.UNKNOWN, + color = _userNamesColors.getOrNull(i) ?: _color.takeIf { it.isNotBlank() }, // optional (fallback: agency color) + target = _userNamesTarget.getOrNull(i)?.takeIf { it.isNotBlank() } + ?: _targetAuthority.takeIf { it.isNotBlank() }, // optional (fallback: agency UUID) + severity = _userNamesSeverity.getOrNull(i) ?: InstagramNewsFeedConfig.SEVERITY_DEFAULT, + noteworthy = _userNamesNoteworthy.getOrNull(i) ?: InstagramNewsFeedConfig.NOTEWORTHY_DEFAULT, + ) + } + ) override fun getLogTag() = LOG_TAG @@ -320,7 +332,7 @@ class InstagramNewsProvider : NewsProvider() { val newNews = ArrayList() val maxValidityInMs = newsMaxValidityInMs val authority = _authority - for ((i, userName) in _userNames.withIndex()) { + _userNames.forEachIndexed { i, userName -> loadUserTimeline( context, getInstagramApi(context), diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt new file mode 100644 index 00000000..8c926f7f --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt @@ -0,0 +1,32 @@ +package org.mtransit.android.commons.provider.config.news.instagram + +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import org.mtransit.android.commons.LocaleUtils +import org.mtransit.android.commons.provider.config.news.NewsFeedConfig + +data class InstagramNewsFeedConfig( + val username: String, + override val target: String? = null, + override val lang: String = LocaleUtils.UNKNOWN, + override val color: String? = null, + override val severity: Int = SEVERITY_DEFAULT, + override val noteworthy: Long = NOTEWORTHY_DEFAULT, +) : NewsFeedConfig { + + companion object { + const val SEVERITY_DEFAULT = 2 // news_provider_severity_info_agency + const val NOTEWORTHY_DEFAULT = 604_800_000L // news_provider_noteworthy_long_term // 1 week + } + + override fun toCursorRow(): Array { + return makeCursorRow( + extra = Json.encodeToString( + buildJsonObject { + put("username", username) + } + ) + ) + } +} diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsProviderConfig.kt new file mode 100644 index 00000000..002f9452 --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsProviderConfig.kt @@ -0,0 +1,7 @@ +package org.mtransit.android.commons.provider.config.news.instagram + +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig + +data class InstagramNewsProviderConfig( + override val newsFeedConfigs: List +) : NewsProviderConfig \ No newline at end of file From fcd309f5a1e4f91badeba0d1f65c5e16a5fbe3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Fri, 20 Jun 2025 22:06:20 -0400 Subject: [PATCH 5/8] RSS v1 --- .../commons/provider/RSSNewsProvider.java | 33 ++++++++++++ .../news/instagram/InstagramNewsFeedConfig.kt | 2 +- .../config/news/rss/RSSNewsFeedConfig.kt | 53 +++++++++++++++++++ .../config/news/rss/RSSNewsProviderConfig.kt | 7 +++ .../provider/news/rss/RssNewProviderUtils.kt | 25 ++++++--- 5 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsProviderConfig.kt diff --git a/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java b/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java index 156c3fe6..73b454ca 100644 --- a/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java @@ -29,6 +29,8 @@ import org.mtransit.android.commons.helpers.MTDefaultHandler; import org.mtransit.android.commons.provider.config.news.DefaultNewsProviderConfig; import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; +import org.mtransit.android.commons.provider.config.news.rss.RSSNewsFeedConfig; +import org.mtransit.android.commons.provider.config.news.rss.RSSNewsProviderConfig; import org.mtransit.android.commons.provider.news.NewsTextFormatter; import org.mtransit.android.commons.provider.news.rss.RssNewProviderUtils; import org.mtransit.commons.CleanUtils; @@ -239,6 +241,37 @@ private static java.util.List getFEEDS_LABEL(@NonNull Context context) { @NonNull @Override public NewsProviderConfig getNewsConfig() { + final Context context = requireContextCompat(); + final ArrayList newsFeedConfigs = new ArrayList<>(); + for (int i = 0; i < getFEEDS(context).size(); i++) { + Integer severity = CollectionUtils.getOrNull(RssNewProviderUtils.getFeedsSeverity(context), i); + if (severity == null) { + severity = RSSNewsFeedConfig.SEVERITY_DEFAULT; + } + Long noteworthy = CollectionUtils.getOrNull(RssNewProviderUtils.getFeedsNoteworthy(context), i); + if (noteworthy == null) { + noteworthy = RSSNewsFeedConfig.NOTEWORTHY_DEFAULT; + } + newsFeedConfigs.add( + new RSSNewsFeedConfig( + getFEEDS(context).get(i), // url + CollectionUtils.getOrNull(getFEEDS_LABEL(context), i), + getFEEDS_AUTHOR_ICON(context).get(i), + CollectionUtils.getOrNull(RssNewProviderUtils.getFeedsAuthorName(context), i), + getFEEDS_AUTHOR_URL(context).get(i), + RssNewProviderUtils.pickEncoding(context), + isCOPY_TO_FILE_INSTEAD_OF_STREAMING(context), + RssNewProviderUtils.pickIgnoreGUID(context, i), + RssNewProviderUtils.pickIgnoreLink(context, i), + RssNewProviderUtils.getTargetOrNull(context, i), + RssNewProviderUtils.pickLang(context, i), + RssNewProviderUtils.getColorOrNull(context, i), + severity, + noteworthy + ) + ); + } + return new RSSNewsProviderConfig(newsFeedConfigs); } @NonNull diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt index 8c926f7f..5bc61b3c 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt @@ -9,7 +9,7 @@ import org.mtransit.android.commons.provider.config.news.NewsFeedConfig data class InstagramNewsFeedConfig( val username: String, override val target: String? = null, - override val lang: String = LocaleUtils.UNKNOWN, + override val lang: String = LocaleUtils.UNKNOWN, // show all override val color: String? = null, override val severity: Int = SEVERITY_DEFAULT, override val noteworthy: Long = NOTEWORTHY_DEFAULT, diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt new file mode 100644 index 00000000..540b933b --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt @@ -0,0 +1,53 @@ +package org.mtransit.android.commons.provider.config.news.rss + +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import org.mtransit.android.commons.LocaleUtils +import org.mtransit.android.commons.provider.config.news.NewsFeedConfig + +data class RSSNewsFeedConfig( + val url: String, // rss feed url + val label: String? = null, // should be guessed from url + val authorIcon: String? = null, + val authorName: String? = null, // fallback to agency short name + val authorUrl: String, + val encoding: String = "UTF-8", + val copyFile: Boolean = COPY_FILE_DEFAULT, // instead of streaming + val ignoreGUID: Boolean = IGNORE_GUID_DEFAULT, + val ignoreLink: Boolean = IGNORE_LINK_DEFAULT, + override val target: String? = null, + override val lang: String = LocaleUtils.UNKNOWN, // show all + override val color: String? = null, + override val severity: Int = SEVERITY_DEFAULT, + override val noteworthy: Long = NOTEWORTHY_DEFAULT, +) : NewsFeedConfig { + + companion object { + const val SEVERITY_DEFAULT = 2 // news_provider_severity_info_agency + const val NOTEWORTHY_DEFAULT = 10_800_000L // news_provider_noteworthy_warning // 3 hours + + const val COPY_FILE_DEFAULT = false + const val IGNORE_GUID_DEFAULT = false + const val IGNORE_LINK_DEFAULT = false + } + + override fun toCursorRow(): Array { + return makeCursorRow( + extra = Json.encodeToString( + buildJsonObject { + put("url", url) + label?.let { put("label", it) } + authorIcon?.let { put("authorIcon", it) } + authorName?.let { put("authorName", it) } + put("authorUrl", authorUrl) + put("encoding", encoding) + if (copyFile != COPY_FILE_DEFAULT) put("copyFile", copyFile) + if (ignoreGUID != IGNORE_GUID_DEFAULT) put("ignoreGUID", ignoreGUID) + if (ignoreLink != IGNORE_LINK_DEFAULT) put("ignoreLink", ignoreLink) + + } + ) + ) + } +} diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsProviderConfig.kt new file mode 100644 index 00000000..b27cf3dd --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsProviderConfig.kt @@ -0,0 +1,7 @@ +package org.mtransit.android.commons.provider.config.news.rss + +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig + +data class RSSNewsProviderConfig( + override val newsFeedConfigs: List +) : NewsProviderConfig \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/news/rss/RssNewProviderUtils.kt b/src/main/java/org/mtransit/android/commons/provider/news/rss/RssNewProviderUtils.kt index 46d26cde..798785ae 100644 --- a/src/main/java/org/mtransit/android/commons/provider/news/rss/RssNewProviderUtils.kt +++ b/src/main/java/org/mtransit/android/commons/provider/news/rss/RssNewProviderUtils.kt @@ -31,17 +31,22 @@ object RssNewProviderUtils : MTLog.Loggable { @JvmStatic fun pickColor(context: Context, i: Int) = - getFeedsColors(context).getOrNull(i)?.takeIf { it.isNotBlank() } - ?: getColor(context).takeIf { it.isNotBlank() } + getColorOrNull(context, i) ?: AgencyUtils.getAgencyColor(context) ?: ColorUtils.BLACK .also { MTLog.w(this, "No color found for '$i'! (used fallback)") } + @JvmStatic + fun getColorOrNull(context: Context, i: Int): String? = + getFeedsColors(context).getOrNull(i)?.takeIf { it.isNotBlank() } + ?: getColor(context).takeIf { it.isNotBlank() } + private var _feedsAuthorName: List? = null - private fun getFeedsAuthorName(context: Context) = _feedsAuthorName + @JvmStatic + fun getFeedsAuthorName(context: Context) = _feedsAuthorName ?: context.resources.getStringArray( R.array.rss_feeds_author_name ).toList() @@ -117,14 +122,19 @@ object RssNewProviderUtils : MTLog.Loggable { @JvmStatic fun pickTarget(context: Context, i: Int): String? { - return getFeedsTarget(context).getOrNull(i)?.takeIf { it.isNotBlank() } - ?: getTargetAuthority(context).takeIf { it.isNotBlank() } + return getTargetOrNull(context, i) ?: AgencyUtils.getAgencyAuthority(context) } + @JvmStatic + fun getTargetOrNull(context: Context, i: Int) = + getFeedsTarget(context).getOrNull(i)?.takeIf { it.isNotBlank() } + ?: getTargetAuthority(context).takeIf { it.isNotBlank() } + private var _feedsSeverity: List? = null - private fun getFeedsSeverity(context: Context) = _feedsSeverity + @JvmStatic + fun getFeedsSeverity(context: Context) = _feedsSeverity ?: context.resources.getIntArray( R.array.rss_feeds_severity ).toList() @@ -138,7 +148,8 @@ object RssNewProviderUtils : MTLog.Loggable { private var _feedsNoteworthy: List? = null - private fun getFeedsNoteworthy(context: Context) = _feedsNoteworthy + @JvmStatic + fun getFeedsNoteworthy(context: Context) = _feedsNoteworthy ?: context.resources.getStringArray( R.array.rss_feeds_noteworthy ).toList().map { it.toLong() } From 1353bfc49014454fe937668721f3cb662b3e5920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Fri, 20 Jun 2025 22:09:17 -0400 Subject: [PATCH 6/8] RSS v2 --- .../commons/provider/RSSNewsProvider.java | 35 +--------- .../config/news/rss/RSSNewsFeedConfig.kt | 7 +- .../provider/news/rss/RssNewProviderUtils.kt | 68 +++++++++++++++---- 3 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java b/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java index 73b454ca..3fa294e2 100644 --- a/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/RSSNewsProvider.java @@ -27,10 +27,7 @@ import org.mtransit.android.commons.UriUtils; import org.mtransit.android.commons.data.News; import org.mtransit.android.commons.helpers.MTDefaultHandler; -import org.mtransit.android.commons.provider.config.news.DefaultNewsProviderConfig; import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; -import org.mtransit.android.commons.provider.config.news.rss.RSSNewsFeedConfig; -import org.mtransit.android.commons.provider.config.news.rss.RSSNewsProviderConfig; import org.mtransit.android.commons.provider.news.NewsTextFormatter; import org.mtransit.android.commons.provider.news.rss.RssNewProviderUtils; import org.mtransit.commons.CleanUtils; @@ -241,37 +238,7 @@ private static java.util.List getFEEDS_LABEL(@NonNull Context context) { @NonNull @Override public NewsProviderConfig getNewsConfig() { - final Context context = requireContextCompat(); - final ArrayList newsFeedConfigs = new ArrayList<>(); - for (int i = 0; i < getFEEDS(context).size(); i++) { - Integer severity = CollectionUtils.getOrNull(RssNewProviderUtils.getFeedsSeverity(context), i); - if (severity == null) { - severity = RSSNewsFeedConfig.SEVERITY_DEFAULT; - } - Long noteworthy = CollectionUtils.getOrNull(RssNewProviderUtils.getFeedsNoteworthy(context), i); - if (noteworthy == null) { - noteworthy = RSSNewsFeedConfig.NOTEWORTHY_DEFAULT; - } - newsFeedConfigs.add( - new RSSNewsFeedConfig( - getFEEDS(context).get(i), // url - CollectionUtils.getOrNull(getFEEDS_LABEL(context), i), - getFEEDS_AUTHOR_ICON(context).get(i), - CollectionUtils.getOrNull(RssNewProviderUtils.getFeedsAuthorName(context), i), - getFEEDS_AUTHOR_URL(context).get(i), - RssNewProviderUtils.pickEncoding(context), - isCOPY_TO_FILE_INSTEAD_OF_STREAMING(context), - RssNewProviderUtils.pickIgnoreGUID(context, i), - RssNewProviderUtils.pickIgnoreLink(context, i), - RssNewProviderUtils.getTargetOrNull(context, i), - RssNewProviderUtils.pickLang(context, i), - RssNewProviderUtils.getColorOrNull(context, i), - severity, - noteworthy - ) - ); - } - return new RSSNewsProviderConfig(newsFeedConfigs); + return RssNewProviderUtils.getNewsConfig(requireContextCompat()); } @NonNull diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt index 540b933b..fbbebbc7 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt @@ -12,8 +12,8 @@ data class RSSNewsFeedConfig( val authorIcon: String? = null, val authorName: String? = null, // fallback to agency short name val authorUrl: String, - val encoding: String = "UTF-8", - val copyFile: Boolean = COPY_FILE_DEFAULT, // instead of streaming + val encoding: String = ENCODING_DEFAULT, + val copyToFile: Boolean = COPY_FILE_DEFAULT, // instead of streaming val ignoreGUID: Boolean = IGNORE_GUID_DEFAULT, val ignoreLink: Boolean = IGNORE_LINK_DEFAULT, override val target: String? = null, @@ -27,6 +27,7 @@ data class RSSNewsFeedConfig( const val SEVERITY_DEFAULT = 2 // news_provider_severity_info_agency const val NOTEWORTHY_DEFAULT = 10_800_000L // news_provider_noteworthy_warning // 3 hours + const val ENCODING_DEFAULT = "UTF-8" const val COPY_FILE_DEFAULT = false const val IGNORE_GUID_DEFAULT = false const val IGNORE_LINK_DEFAULT = false @@ -42,7 +43,7 @@ data class RSSNewsFeedConfig( authorName?.let { put("authorName", it) } put("authorUrl", authorUrl) put("encoding", encoding) - if (copyFile != COPY_FILE_DEFAULT) put("copyFile", copyFile) + if (copyToFile != COPY_FILE_DEFAULT) put("copyToFile", copyToFile) if (ignoreGUID != IGNORE_GUID_DEFAULT) put("ignoreGUID", ignoreGUID) if (ignoreLink != IGNORE_LINK_DEFAULT) put("ignoreLink", ignoreLink) diff --git a/src/main/java/org/mtransit/android/commons/provider/news/rss/RssNewProviderUtils.kt b/src/main/java/org/mtransit/android/commons/provider/news/rss/RssNewProviderUtils.kt index 798785ae..35b2e532 100644 --- a/src/main/java/org/mtransit/android/commons/provider/news/rss/RssNewProviderUtils.kt +++ b/src/main/java/org/mtransit/android/commons/provider/news/rss/RssNewProviderUtils.kt @@ -6,6 +6,9 @@ import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.MTLog import org.mtransit.android.commons.R import org.mtransit.android.commons.provider.agency.AgencyUtils +import org.mtransit.android.commons.provider.config.news.NewsProviderConfig +import org.mtransit.android.commons.provider.config.news.rss.RSSNewsFeedConfig +import org.mtransit.android.commons.provider.config.news.rss.RSSNewsProviderConfig import org.mtransit.commons.dropWhile import java.net.URL @@ -15,6 +18,14 @@ object RssNewProviderUtils : MTLog.Loggable { override fun getLogTag() = LOG_TAG + private var _feeds: List? = null + + private fun getFeeds(context: Context) = _feeds + ?: context.resources.getStringArray( + R.array.rss_feeds + ).toList() + .also { _feeds = it } + private var _color: String? = null private fun getColor(context: Context) = _color @@ -29,6 +40,10 @@ object RssNewProviderUtils : MTLog.Loggable { ).toList() .also { _feedsColors = it } + private fun getColorOrNull(context: Context, i: Int): String? = + getFeedsColors(context).getOrNull(i)?.takeIf { it.isNotBlank() } + ?: getColor(context).takeIf { it.isNotBlank() } + @JvmStatic fun pickColor(context: Context, i: Int) = getColorOrNull(context, i) @@ -38,15 +53,9 @@ object RssNewProviderUtils : MTLog.Loggable { MTLog.w(this, "No color found for '$i'! (used fallback)") } - @JvmStatic - fun getColorOrNull(context: Context, i: Int): String? = - getFeedsColors(context).getOrNull(i)?.takeIf { it.isNotBlank() } - ?: getColor(context).takeIf { it.isNotBlank() } - private var _feedsAuthorName: List? = null - @JvmStatic - fun getFeedsAuthorName(context: Context) = _feedsAuthorName + private fun getFeedsAuthorName(context: Context) = _feedsAuthorName ?: context.resources.getStringArray( R.array.rss_feeds_author_name ).toList() @@ -57,6 +66,14 @@ object RssNewProviderUtils : MTLog.Loggable { getFeedsAuthorName(context).getOrNull(i)?.takeIf { it.isNotBlank() } ?: AgencyUtils.getAgencyShortName(context) + private var _feedsAuthorUrl: List? = null + + private fun getFeedsAuthorUrl(context: Context) = _feedsAuthorUrl + ?: context.resources.getStringArray( + R.array.rss_feeds_author_url + ).toList() + .also { _feedsAuthorUrl = it } + private val LABEL_BLACK_LIST = listOf( "api", "assets", @@ -126,15 +143,13 @@ object RssNewProviderUtils : MTLog.Loggable { ?: AgencyUtils.getAgencyAuthority(context) } - @JvmStatic - fun getTargetOrNull(context: Context, i: Int) = + private fun getTargetOrNull(context: Context, i: Int) = getFeedsTarget(context).getOrNull(i)?.takeIf { it.isNotBlank() } ?: getTargetAuthority(context).takeIf { it.isNotBlank() } private var _feedsSeverity: List? = null - @JvmStatic - fun getFeedsSeverity(context: Context) = _feedsSeverity + private fun getFeedsSeverity(context: Context) = _feedsSeverity ?: context.resources.getIntArray( R.array.rss_feeds_severity ).toList() @@ -148,8 +163,7 @@ object RssNewProviderUtils : MTLog.Loggable { private var _feedsNoteworthy: List? = null - @JvmStatic - fun getFeedsNoteworthy(context: Context) = _feedsNoteworthy + private fun getFeedsNoteworthy(context: Context) = _feedsNoteworthy ?: context.resources.getStringArray( R.array.rss_feeds_noteworthy ).toList().map { it.toLong() } @@ -199,8 +213,36 @@ object RssNewProviderUtils : MTLog.Loggable { ?: context.resources.getString(R.string.rss_encoding) .also { _encoding = it } + private var _copyToFile: Boolean? = null + + private fun getCopyToFile(context: Context) = _copyToFile + ?: context.resources.getBoolean(R.bool.rss_copy_to_file_instead_of_streaming) + .also { _copyToFile = it } + @JvmStatic fun pickEncoding(context: Context) = getEncoding(context).takeIf { it.isNotBlank() } ?: ENCODING_DEFAULT + + @JvmStatic + fun getNewsConfig(context: Context): NewsProviderConfig = RSSNewsProviderConfig( + newsFeedConfigs = getFeeds(context).mapIndexed { i, url -> + RSSNewsFeedConfig( + url = url, + label = pickLabel(url), + authorIcon = getFeedsColors(context).getOrNull(i), + authorName = getFeedsAuthorName(context).getOrNull(i), + authorUrl = getFeedsAuthorUrl(context)[i], // mandatory + encoding = pickEncoding(context), + copyToFile = getCopyToFile(context), + ignoreGUID = pickIgnoreGUID(context, i), + ignoreLink = pickIgnoreLink(context, i), + target = getTargetOrNull(context, i), + lang = pickLang(context, i), + color = getColorOrNull(context, i), + severity = getFeedsSeverity(context).getOrNull(i) ?: RSSNewsFeedConfig.SEVERITY_DEFAULT, + noteworthy = getFeedsNoteworthy(context).getOrNull(i) ?: RSSNewsFeedConfig.NOTEWORTHY_DEFAULT, + ) + } + ) } \ No newline at end of file From 6b142e3a9a9a8503f9bb5ef9f9c4e8005f5e83f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Wed, 25 Jun 2025 21:11:20 -0400 Subject: [PATCH 7/8] add fromCursor() + news provider type --- .../android/commons/data/DefaultPOI.java | 2 +- .../commons/provider/CaSTOProvider.java | 3 +- .../commons/provider/NewsProvider.java | 2 +- .../provider/NewsProviderContract.java | 1 + .../provider/WinnipegTransitProvider.java | 3 +- .../config/news/DefaultNewsProviderConfig.kt | 14 ++++- .../provider/config/news/NewsFeedConfig.kt | 24 +++++++- .../config/news/NewsProviderConfig.kt | 26 ++++++++- .../commons/provider/config/news/NewsType.kt | 18 ++++++ .../news/instagram/InstagramNewsFeedConfig.kt | 37 ++++++++++++ .../instagram/InstagramNewsProviderConfig.kt | 12 +++- .../config/news/rss/RSSNewsFeedConfig.kt | 56 ++++++++++++++++++- .../config/news/rss/RSSNewsProviderConfig.kt | 12 +++- .../news/twitter/TwitterNewsFeedConfig.kt | 39 +++++++++++++ .../news/twitter/TwitterNewsProviderConfig.kt | 12 +++- .../news/youtube/YouTubeNewsFeedConfig.kt | 44 +++++++++++++++ .../news/youtube/YouTubeNewsProviderConfig.kt | 12 +++- 17 files changed, 302 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/mtransit/android/commons/provider/config/news/NewsType.kt diff --git a/src/main/java/org/mtransit/android/commons/data/DefaultPOI.java b/src/main/java/org/mtransit/android/commons/data/DefaultPOI.java index e83588a1..31190cbf 100644 --- a/src/main/java/org/mtransit/android/commons/data/DefaultPOI.java +++ b/src/main/java/org/mtransit/android/commons/data/DefaultPOI.java @@ -278,7 +278,7 @@ public static DefaultPOI fromCursorStatic(@NonNull Cursor c, @NonNull String aut authority, getIdFromCursor(c), getDataSourceTypeIdFromCursor(c), - c.getInt(c.getColumnIndexOrThrow(POIProviderContract.Columns.T_POI_K_TYPE)), + getTypeFromCursor(c), c.getInt(c.getColumnIndexOrThrow(POIProviderContract.Columns.T_POI_K_STATUS_TYPE)), CursorExtKt.optIntNN(c, POIProviderContract.Columns.T_POI_K_ACTIONS_TYPE, POI.ITEM_ACTION_TYPE_NONE) ); diff --git a/src/main/java/org/mtransit/android/commons/provider/CaSTOProvider.java b/src/main/java/org/mtransit/android/commons/provider/CaSTOProvider.java index 0b1a5bab..15f33b8b 100644 --- a/src/main/java/org/mtransit/android/commons/provider/CaSTOProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/CaSTOProvider.java @@ -31,6 +31,7 @@ import org.mtransit.android.commons.helpers.MTDefaultHandler; import org.mtransit.android.commons.provider.config.news.DefaultNewsProviderConfig; import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; +import org.mtransit.android.commons.provider.config.news.NewsType; import org.mtransit.android.commons.provider.news.NewsTextFormatter; import org.mtransit.commons.SourceUtils; import org.xml.sax.Attributes; @@ -165,7 +166,7 @@ private static String getNEWS_TARGET_AUTHORITY(@NonNull Context context) { @NonNull @Override public NewsProviderConfig getNewsConfig() { - return new DefaultNewsProviderConfig(); + return new DefaultNewsProviderConfig(NewsType.CA_STO); } /** diff --git a/src/main/java/org/mtransit/android/commons/provider/NewsProvider.java b/src/main/java/org/mtransit/android/commons/provider/NewsProvider.java index 2838ee32..84086d36 100644 --- a/src/main/java/org/mtransit/android/commons/provider/NewsProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/NewsProvider.java @@ -151,7 +151,7 @@ public static Cursor queryS(@NonNull NewsProviderContract provider, @NonNull Uri } } - @Nullable + @NonNull private static Cursor getNewsConfig(@NonNull NewsProviderContract provider) { final NewsProviderConfig providerNewsConfig = provider.getNewsConfig(); return providerNewsConfig.toCursor(); diff --git a/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java b/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java index e4d63f05..2157835e 100644 --- a/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java +++ b/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java @@ -139,6 +139,7 @@ interface Columns { }; interface FeedConfigColumns { + String T_NEWS_FEED_CONFIG_K_TYPE = "type"; String T_NEWS_FEED_CONFIG_K_TARGET = "target"; String T_NEWS_FEED_CONFIG_K_LANG = "lang"; String T_NEWS_FEED_CONFIG_K_COLOR = "color"; diff --git a/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java b/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java index 81aceffe..88873feb 100644 --- a/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java +++ b/src/main/java/org/mtransit/android/commons/provider/WinnipegTransitProvider.java @@ -41,6 +41,7 @@ import org.mtransit.android.commons.data.Trip; import org.mtransit.android.commons.provider.config.news.DefaultNewsProviderConfig; import org.mtransit.android.commons.provider.config.news.NewsProviderConfig; +import org.mtransit.android.commons.provider.config.news.NewsType; import org.mtransit.commons.CleanUtils; import org.mtransit.commons.FeatureFlags; import org.mtransit.commons.SourceUtils; @@ -186,7 +187,7 @@ private static String getNEWS_TARGET_AUTHORITY(@NonNull Context context) { @NonNull @Override public NewsProviderConfig getNewsConfig() { - return new DefaultNewsProviderConfig(); + return new DefaultNewsProviderConfig(NewsType.CA_WINNIPEG); } private static final long WEB_SERVICE_STATUS_MAX_VALIDITY_IN_MS = TimeUnit.HOURS.toMillis(1L); diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt index 78ab867c..751631c8 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt @@ -1,5 +1,17 @@ package org.mtransit.android.commons.provider.config.news +import android.database.Cursor +import org.mtransit.android.commons.provider.NewsProviderContract.FeedConfigColumns + data class DefaultNewsProviderConfig @JvmOverloads constructor( + override val type: NewsType, override val newsFeedConfigs: List = emptyList() -) : NewsProviderConfig +) : NewsProviderConfig { + companion object { + fun getTypeFromCursor(cursor: Cursor): NewsType? = NewsType.fromId( + cursor.getInt(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_TYPE)) + ) + + fun fromCursor(newsType: NewsType): NewsProviderConfig = DefaultNewsProviderConfig(newsType,) + } +} diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt index cc0e1923..73fdd81b 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt @@ -1,5 +1,7 @@ package org.mtransit.android.commons.provider.config.news +import android.database.Cursor +import androidx.core.database.getStringOrNull import org.mtransit.android.commons.LocaleUtils interface NewsFeedConfig { @@ -13,9 +15,7 @@ interface NewsFeedConfig { * See [org.mtransit.android.commons.provider.NewsProviderContract.FeedConfigColumns] * See [org.mtransit.android.commons.provider.NewsProviderContract.PROJECTION_NEWS_FEED_CONFIG] */ - fun toCursorRow(): Array { - return makeCursorRow() - } + fun toCursorRow(): Array fun makeCursorRow(extra: String? = null) = arrayOf( target.orEmpty(), @@ -25,4 +25,22 @@ interface NewsFeedConfig { noteworthy, extra.orEmpty(), ) + + fun fromCursorRow(row: Array): NewsFeedConfig + + companion object { + fun getTargetFromCursorRow(row: Array): String? = (row.getOrNull(0) as? String)?.takeIf { it.isNotEmpty() } + fun getLangFromCursorRow(row: Array): String = row[1] as String + fun getColorFromCursorRow(row: Array): String? = (row.getOrNull(2) as? String)?.takeIf { it.isNotEmpty() } + fun getSeverityFromCursorRow(row: Array): Int = row[3] as Int + fun getNoteworthyFromCursorRow(row: Array): Long = row[4] as Long + fun getExtraFromCursorRow(row: Array): String? = (row.getOrNull(5) as? String)?.takeIf { it.isNotEmpty() } + + fun getTargetFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow("target")) + fun getLangFromCursorRow(cursor: Cursor): String = cursor.getString(cursor.getColumnIndexOrThrow("lang")) + fun getColorFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow("color")) + fun getSeverityFromCursorRow(cursor: Cursor): Int = cursor.getInt(cursor.getColumnIndexOrThrow("severity")) + fun getNoteworthyFromCursorRow(cursor: Cursor): Long = cursor.getLong(cursor.getColumnIndexOrThrow("noteworthy")) + fun getExtraFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow("extra")) + } } \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsProviderConfig.kt index fe0ed3e0..fb4c946a 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsProviderConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsProviderConfig.kt @@ -4,14 +4,36 @@ import android.database.Cursor import android.database.MatrixCursor import org.mtransit.android.commons.provider.NewsProviderContract import org.mtransit.android.commons.provider.config.ProviderConfig +import org.mtransit.android.commons.provider.config.news.instagram.InstagramNewsProviderConfig +import org.mtransit.android.commons.provider.config.news.rss.RSSNewsProviderConfig +import org.mtransit.android.commons.provider.config.news.twitter.TwitterNewsProviderConfig +import org.mtransit.android.commons.provider.config.news.youtube.YouTubeNewsProviderConfig interface NewsProviderConfig : ProviderConfig { + val type: NewsType val newsFeedConfigs: List fun toCursor(): Cursor = MatrixCursor(NewsProviderContract.PROJECTION_NEWS_FEED_CONFIG).apply { - newsFeedConfigs.forEach { - addRow(it.toCursorRow()) + newsFeedConfigs.forEach { newsFeedConfig -> + addRow(newsFeedConfig.toCursorRow()) } } + + companion object { + + @JvmStatic + fun fromCursor(cursor: Cursor?): NewsProviderConfig? { + cursor ?: return null + val newsType = DefaultNewsProviderConfig.getTypeFromCursor(cursor) ?: return null + return when (newsType) { + NewsType.RSS -> RSSNewsProviderConfig.fromCursor(cursor) + NewsType.YOUTUBE -> YouTubeNewsProviderConfig.fromCursor(cursor) + NewsType.TWITTER -> TwitterNewsProviderConfig.fromCursor(cursor) + NewsType.INSTAGRAM -> InstagramNewsProviderConfig.fromCursor(cursor) + NewsType.CA_STO -> DefaultNewsProviderConfig.fromCursor(newsType) + NewsType.CA_WINNIPEG -> DefaultNewsProviderConfig.fromCursor(newsType) + } + } + } } \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsType.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsType.kt new file mode 100644 index 00000000..38fc422e --- /dev/null +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsType.kt @@ -0,0 +1,18 @@ +package org.mtransit.android.commons.provider.config.news + +enum class NewsType(val id: Int) { + + RSS(0), + YOUTUBE(1), + TWITTER(2), + INSTAGRAM(3), + + CA_STO(100), + CA_WINNIPEG(101), + + ; + + companion object { + fun fromId(id: Int) = entries.singleOrNull { it.id == id } + } +} \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt index 5bc61b3c..64fc7c90 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt @@ -1,10 +1,15 @@ package org.mtransit.android.commons.provider.config.news.instagram +import android.database.Cursor import kotlinx.serialization.json.Json import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.put import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.provider.config.news.NewsFeedConfig +import org.mtransit.android.commons.provider.config.news.rss.RSSNewsFeedConfig +import java.lang.IllegalStateException data class InstagramNewsFeedConfig( val username: String, @@ -18,6 +23,25 @@ data class InstagramNewsFeedConfig( companion object { const val SEVERITY_DEFAULT = 2 // news_provider_severity_info_agency const val NOTEWORTHY_DEFAULT = 604_800_000L // news_provider_noteworthy_long_term // 1 week + + fun fromCursor(cursor: Cursor) = buildList { + while (cursor.moveToNext()) { + add(fromCursorRow(cursor)) + } + } + + private fun fromCursorRow(cursor: Cursor): InstagramNewsFeedConfig { + val extraFromCursorRow = NewsFeedConfig.getExtraFromCursorRow(cursor) ?: throw IllegalStateException("Extra is missing") + val extra = Json.parseToJsonElement(extraFromCursorRow).jsonObject + return InstagramNewsFeedConfig( + username = extra["username"]?.jsonPrimitive?.content ?: throw IllegalArgumentException("Missing username"), + target = NewsFeedConfig.getTargetFromCursorRow(cursor), + lang = NewsFeedConfig.getLangFromCursorRow(cursor), + color = NewsFeedConfig.getColorFromCursorRow(cursor), + severity = NewsFeedConfig.getSeverityFromCursorRow(cursor), + noteworthy = NewsFeedConfig.getNoteworthyFromCursorRow(cursor), + ) + } } override fun toCursorRow(): Array { @@ -29,4 +53,17 @@ data class InstagramNewsFeedConfig( ) ) } + + override fun fromCursorRow(row: Array): NewsFeedConfig { + val extraFromCursorRow = NewsFeedConfig.getExtraFromCursorRow(row) ?: throw IllegalStateException("Extra is missing") + val extra = Json.parseToJsonElement(extraFromCursorRow).jsonObject + return InstagramNewsFeedConfig( + username = extra["username"]?.jsonPrimitive?.content ?: throw IllegalArgumentException("Missing username"), + target = NewsFeedConfig.getTargetFromCursorRow(row), + lang = NewsFeedConfig.getLangFromCursorRow(row), + color = NewsFeedConfig.getColorFromCursorRow(row), + severity = NewsFeedConfig.getSeverityFromCursorRow(row), + noteworthy = NewsFeedConfig.getNoteworthyFromCursorRow(row), + ) + } } diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsProviderConfig.kt index 002f9452..41b0a669 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsProviderConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsProviderConfig.kt @@ -1,7 +1,17 @@ package org.mtransit.android.commons.provider.config.news.instagram +import android.database.Cursor import org.mtransit.android.commons.provider.config.news.NewsProviderConfig +import org.mtransit.android.commons.provider.config.news.NewsType data class InstagramNewsProviderConfig( override val newsFeedConfigs: List -) : NewsProviderConfig \ No newline at end of file +) : NewsProviderConfig { + override val type = NewsType.INSTAGRAM + + companion object { + fun fromCursor(cursor: Cursor)= InstagramNewsProviderConfig( + newsFeedConfigs = InstagramNewsFeedConfig.fromCursor(cursor) + ) + } +} diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt index fbbebbc7..1efbd51a 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt @@ -1,10 +1,16 @@ package org.mtransit.android.commons.provider.config.news.rss +import android.database.Cursor import kotlinx.serialization.json.Json +import kotlinx.serialization.json.booleanOrNull import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.put import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.provider.config.news.NewsFeedConfig +import java.lang.IllegalStateException data class RSSNewsFeedConfig( val url: String, // rss feed url @@ -31,8 +37,36 @@ data class RSSNewsFeedConfig( const val COPY_FILE_DEFAULT = false const val IGNORE_GUID_DEFAULT = false const val IGNORE_LINK_DEFAULT = false + + fun fromCursor(cursor: Cursor) = buildList { + while (cursor.moveToNext()) { + add(fromCursorRow(cursor)) + } + } + + private fun fromCursorRow(cursor: Cursor): RSSNewsFeedConfig { + val extraFromCursorRow = NewsFeedConfig.getExtraFromCursorRow(cursor) ?: throw IllegalStateException("Extra is missing") + val extra = Json.parseToJsonElement(extraFromCursorRow).jsonObject + return RSSNewsFeedConfig( + url = extra["url"]?.jsonPrimitive?.content ?: throw IllegalStateException("URL is missing"), + label = extra["label"]?.jsonPrimitive?.contentOrNull, + authorIcon = extra["authorIcon"]?.jsonPrimitive?.contentOrNull, + authorName = extra["authorName"]?.jsonPrimitive?.contentOrNull, + authorUrl = extra["authorUrl"]?.jsonPrimitive?.content ?: throw IllegalStateException("Author URL is missing"), + encoding = extra["encoding"]?.jsonPrimitive?.contentOrNull ?: ENCODING_DEFAULT, + copyToFile = extra["copyToFile"]?.jsonPrimitive?.booleanOrNull ?: COPY_FILE_DEFAULT, + ignoreGUID = extra["ignoreGUID"]?.jsonPrimitive?.booleanOrNull ?: IGNORE_GUID_DEFAULT, + ignoreLink = extra["ignoreLink"]?.jsonPrimitive?.booleanOrNull ?: IGNORE_LINK_DEFAULT, + target = NewsFeedConfig.getTargetFromCursorRow(cursor), + lang = NewsFeedConfig.getLangFromCursorRow(cursor), + color = NewsFeedConfig.getColorFromCursorRow(cursor), + severity = NewsFeedConfig.getSeverityFromCursorRow(cursor), + noteworthy = NewsFeedConfig.getNoteworthyFromCursorRow(cursor), + ) + } } + @Suppress("SimplifyBooleanWithConstants") override fun toCursorRow(): Array { return makeCursorRow( extra = Json.encodeToString( @@ -46,9 +80,29 @@ data class RSSNewsFeedConfig( if (copyToFile != COPY_FILE_DEFAULT) put("copyToFile", copyToFile) if (ignoreGUID != IGNORE_GUID_DEFAULT) put("ignoreGUID", ignoreGUID) if (ignoreLink != IGNORE_LINK_DEFAULT) put("ignoreLink", ignoreLink) - } ) ) } + + override fun fromCursorRow(row: Array): NewsFeedConfig { + val extraFromCursorRow = NewsFeedConfig.getExtraFromCursorRow(row) ?: throw IllegalStateException("Extra is missing") + val extra = Json.parseToJsonElement(extraFromCursorRow).jsonObject + return RSSNewsFeedConfig( + url = extra["url"]?.jsonPrimitive?.content ?: throw IllegalStateException("URL is missing"), + label = extra["label"]?.jsonPrimitive?.contentOrNull, + authorIcon = extra["authorIcon"]?.jsonPrimitive?.contentOrNull, + authorName = extra["authorName"]?.jsonPrimitive?.contentOrNull, + authorUrl = extra["authorUrl"]?.jsonPrimitive?.content ?: throw IllegalStateException("Author URL is missing"), + encoding = extra["encoding"]?.jsonPrimitive?.contentOrNull ?: ENCODING_DEFAULT, + copyToFile = extra["copyToFile"]?.jsonPrimitive?.booleanOrNull ?: COPY_FILE_DEFAULT, + ignoreGUID = extra["ignoreGUID"]?.jsonPrimitive?.booleanOrNull ?: IGNORE_GUID_DEFAULT, + ignoreLink = extra["ignoreLink"]?.jsonPrimitive?.booleanOrNull ?: IGNORE_LINK_DEFAULT, + target = NewsFeedConfig.getTargetFromCursorRow(row), + lang = NewsFeedConfig.getLangFromCursorRow(row), + color = NewsFeedConfig.getColorFromCursorRow(row), + severity = NewsFeedConfig.getSeverityFromCursorRow(row), + noteworthy = NewsFeedConfig.getNoteworthyFromCursorRow(row), + ) + } } diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsProviderConfig.kt index b27cf3dd..d01ab47f 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsProviderConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsProviderConfig.kt @@ -1,7 +1,17 @@ package org.mtransit.android.commons.provider.config.news.rss +import android.database.Cursor import org.mtransit.android.commons.provider.config.news.NewsProviderConfig +import org.mtransit.android.commons.provider.config.news.NewsType data class RSSNewsProviderConfig( override val newsFeedConfigs: List -) : NewsProviderConfig \ No newline at end of file +) : NewsProviderConfig { + override val type = NewsType.RSS + + companion object { + fun fromCursor(cursor: Cursor) = RSSNewsProviderConfig( + newsFeedConfigs = RSSNewsFeedConfig.fromCursor(cursor) + ) + } +} diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt index 73c804f9..9483a267 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt @@ -1,10 +1,15 @@ package org.mtransit.android.commons.provider.config.news.twitter +import android.database.Cursor import kotlinx.serialization.json.Json import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.put import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.provider.config.news.NewsFeedConfig +import java.lang.IllegalStateException data class TwitterNewsFeedConfig( val username: String, @@ -19,6 +24,26 @@ data class TwitterNewsFeedConfig( companion object { const val SEVERITY_DEFAULT = 2 // news_provider_severity_info_agency const val NOTEWORTHY_DEFAULT = 10_800_000L // news_provider_noteworthy_warning // 3 hours + + fun fromCursor(cursor: Cursor) = buildList { + while (cursor.moveToNext()) { + add(fromCursorRow(cursor)) + } + } + + private fun fromCursorRow(cursor: Cursor): TwitterNewsFeedConfig { + val extraFromCursorRow = NewsFeedConfig.getExtraFromCursorRow(cursor) ?: throw IllegalStateException("Extra is missing") + val extra = Json.parseToJsonElement(extraFromCursorRow).jsonObject + return TwitterNewsFeedConfig( + username = extra["username"]?.jsonPrimitive?.content ?: throw IllegalStateException("username is missing"), + userId = extra["userId"]?.jsonPrimitive?.contentOrNull, + target = NewsFeedConfig.getTargetFromCursorRow(cursor), + lang = NewsFeedConfig.getLangFromCursorRow(cursor), + color = NewsFeedConfig.getColorFromCursorRow(cursor), + severity = NewsFeedConfig.getSeverityFromCursorRow(cursor), + noteworthy = NewsFeedConfig.getNoteworthyFromCursorRow(cursor), + ) + } } override fun toCursorRow(): Array { @@ -31,4 +56,18 @@ data class TwitterNewsFeedConfig( ) ) } + + override fun fromCursorRow(row: Array): NewsFeedConfig { + val extraFromCursorRow = NewsFeedConfig.getExtraFromCursorRow(row) ?: throw IllegalStateException("Extra is missing") + val extra = Json.parseToJsonElement(extraFromCursorRow).jsonObject + return TwitterNewsFeedConfig( + username = extra["username"]?.jsonPrimitive?.content ?: throw IllegalStateException("username is missing"), + userId = extra["userId"]?.jsonPrimitive?.contentOrNull, + target = NewsFeedConfig.getTargetFromCursorRow(row), + lang = NewsFeedConfig.getLangFromCursorRow(row), + color = NewsFeedConfig.getColorFromCursorRow(row), + severity = NewsFeedConfig.getSeverityFromCursorRow(row), + noteworthy = NewsFeedConfig.getNoteworthyFromCursorRow(row), + ) + } } diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsProviderConfig.kt index f94bd445..b08db669 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsProviderConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsProviderConfig.kt @@ -1,7 +1,17 @@ package org.mtransit.android.commons.provider.config.news.twitter +import android.database.Cursor import org.mtransit.android.commons.provider.config.news.NewsProviderConfig +import org.mtransit.android.commons.provider.config.news.NewsType data class TwitterNewsProviderConfig( override val newsFeedConfigs: List -) : NewsProviderConfig \ No newline at end of file +) : NewsProviderConfig { + override val type = NewsType.TWITTER + + companion object { + fun fromCursor(cursor: Cursor)= TwitterNewsProviderConfig( + newsFeedConfigs = TwitterNewsFeedConfig.fromCursor(cursor) + ) + } +} diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt index bb34cf28..29b54758 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt @@ -1,10 +1,16 @@ package org.mtransit.android.commons.provider.config.news.youtube +import android.database.Cursor import kotlinx.serialization.json.Json import kotlinx.serialization.json.put import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.provider.config.news.NewsFeedConfig +import org.mtransit.android.commons.provider.config.news.rss.RSSNewsFeedConfig +import java.lang.IllegalStateException data class YouTubeNewsFeedConfig( val authorUrl: String, // can extract "username OR @userHandle or channel ID" from url @@ -21,6 +27,28 @@ data class YouTubeNewsFeedConfig( companion object { const val SEVERITY_DEFAULT = 2 // news_provider_severity_info_agency const val NOTEWORTHY_DEFAULT = 604_800_000L // news_provider_noteworthy_long_term // 1 week + + fun fromCursor(cursor: Cursor) = buildList { + while (cursor.moveToNext()) { + add(fromCursorRow(cursor)) + } + } + + private fun fromCursorRow(cursor: Cursor): YouTubeNewsFeedConfig { + val extraFromCursorRow = NewsFeedConfig.getExtraFromCursorRow(cursor) ?: throw IllegalStateException("Extra is missing") + val extra = Json.parseToJsonElement(extraFromCursorRow).jsonObject + return YouTubeNewsFeedConfig( + authorUrl = extra["authorUrl"]?.jsonPrimitive?.content ?: throw IllegalStateException("authorUrl is missing"), + username = extra["username"]?.jsonPrimitive?.contentOrNull, + userHandle = extra["userHandle"]?.jsonPrimitive?.contentOrNull, + channelId = extra["channelId"]?.jsonPrimitive?.contentOrNull, + target = NewsFeedConfig.getTargetFromCursorRow(cursor), + color = NewsFeedConfig.getColorFromCursorRow(cursor), + lang = NewsFeedConfig.getLangFromCursorRow(cursor), + severity = NewsFeedConfig.getSeverityFromCursorRow(cursor), + noteworthy = NewsFeedConfig.getNoteworthyFromCursorRow(cursor), + ) + } } override fun toCursorRow(): Array { @@ -35,4 +63,20 @@ data class YouTubeNewsFeedConfig( ) ) } + + override fun fromCursorRow(row: Array): NewsFeedConfig { + val extraFromCursorRow = NewsFeedConfig.getExtraFromCursorRow(row) ?: throw IllegalStateException("Extra is missing") + val extra = Json.parseToJsonElement(extraFromCursorRow).jsonObject + return YouTubeNewsFeedConfig( + authorUrl = extra["authorUrl"]?.jsonPrimitive?.content ?: throw IllegalStateException("authorUrl is missing"), + username = extra["username"]?.jsonPrimitive?.contentOrNull, + userHandle = extra["userHandle"]?.jsonPrimitive?.contentOrNull, + channelId = extra["channelId"]?.jsonPrimitive?.contentOrNull, + target = NewsFeedConfig.getTargetFromCursorRow(row), + color = NewsFeedConfig.getColorFromCursorRow(row), + lang = NewsFeedConfig.getLangFromCursorRow(row), + severity = NewsFeedConfig.getSeverityFromCursorRow(row), + noteworthy = NewsFeedConfig.getNoteworthyFromCursorRow(row), + ) + } } diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsProviderConfig.kt index 284e6f87..4671c324 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsProviderConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsProviderConfig.kt @@ -1,7 +1,17 @@ package org.mtransit.android.commons.provider.config.news.youtube +import android.database.Cursor import org.mtransit.android.commons.provider.config.news.NewsProviderConfig +import org.mtransit.android.commons.provider.config.news.NewsType data class YouTubeNewsProviderConfig( override val newsFeedConfigs: List -) : NewsProviderConfig \ No newline at end of file +) : NewsProviderConfig { + override val type = NewsType.YOUTUBE + + companion object { + fun fromCursor(cursor: Cursor)= YouTubeNewsProviderConfig( + newsFeedConfigs = YouTubeNewsFeedConfig.fromCursor(cursor) + ) + } +} From f36b28a53624dade16596f06e657a7e5ad724645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Wed, 25 Jun 2025 21:22:35 -0400 Subject: [PATCH 8/8] add missing projection column for type (id) --- .../provider/NewsProviderContract.java | 1 + .../config/news/DefaultNewsProviderConfig.kt | 3 +- .../provider/config/news/NewsFeedConfig.kt | 32 +++++++++++-------- .../news/instagram/InstagramNewsFeedConfig.kt | 3 +- .../config/news/rss/RSSNewsFeedConfig.kt | 2 ++ .../news/twitter/TwitterNewsFeedConfig.kt | 2 ++ .../news/youtube/YouTubeNewsFeedConfig.kt | 3 +- 7 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java b/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java index 2157835e..ad38b2e3 100644 --- a/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java +++ b/src/main/java/org/mtransit/android/commons/provider/NewsProviderContract.java @@ -151,6 +151,7 @@ interface FeedConfigColumns { } String[] PROJECTION_NEWS_FEED_CONFIG = new String[]{ + FeedConfigColumns.T_NEWS_FEED_CONFIG_K_TYPE, FeedConfigColumns.T_NEWS_FEED_CONFIG_K_TARGET, FeedConfigColumns.T_NEWS_FEED_CONFIG_K_LANG, FeedConfigColumns.T_NEWS_FEED_CONFIG_K_COLOR, diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt index 751631c8..1bece66e 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/DefaultNewsProviderConfig.kt @@ -1,7 +1,6 @@ package org.mtransit.android.commons.provider.config.news import android.database.Cursor -import org.mtransit.android.commons.provider.NewsProviderContract.FeedConfigColumns data class DefaultNewsProviderConfig @JvmOverloads constructor( override val type: NewsType, @@ -9,7 +8,7 @@ data class DefaultNewsProviderConfig @JvmOverloads constructor( ) : NewsProviderConfig { companion object { fun getTypeFromCursor(cursor: Cursor): NewsType? = NewsType.fromId( - cursor.getInt(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_TYPE)) + NewsFeedConfig.getTypeIdFromCursorRow(cursor) ) fun fromCursor(newsType: NewsType): NewsProviderConfig = DefaultNewsProviderConfig(newsType,) diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt index 73fdd81b..df46d174 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/NewsFeedConfig.kt @@ -3,6 +3,7 @@ package org.mtransit.android.commons.provider.config.news import android.database.Cursor import androidx.core.database.getStringOrNull import org.mtransit.android.commons.LocaleUtils +import org.mtransit.android.commons.provider.NewsProviderContract.FeedConfigColumns interface NewsFeedConfig { val target: String? get() = null // target the entire agency @@ -12,12 +13,13 @@ interface NewsFeedConfig { val noteworthy: Long get() = 86_400_000L // news_provider_noteworthy_info // 1 days /** - * See [org.mtransit.android.commons.provider.NewsProviderContract.FeedConfigColumns] + * See [FeedConfigColumns] * See [org.mtransit.android.commons.provider.NewsProviderContract.PROJECTION_NEWS_FEED_CONFIG] */ fun toCursorRow(): Array - fun makeCursorRow(extra: String? = null) = arrayOf( + fun makeCursorRow(type: NewsType, extra: String? = null) = arrayOf( + type.id, target.orEmpty(), lang, color.orEmpty(), @@ -29,18 +31,20 @@ interface NewsFeedConfig { fun fromCursorRow(row: Array): NewsFeedConfig companion object { - fun getTargetFromCursorRow(row: Array): String? = (row.getOrNull(0) as? String)?.takeIf { it.isNotEmpty() } - fun getLangFromCursorRow(row: Array): String = row[1] as String - fun getColorFromCursorRow(row: Array): String? = (row.getOrNull(2) as? String)?.takeIf { it.isNotEmpty() } - fun getSeverityFromCursorRow(row: Array): Int = row[3] as Int - fun getNoteworthyFromCursorRow(row: Array): Long = row[4] as Long - fun getExtraFromCursorRow(row: Array): String? = (row.getOrNull(5) as? String)?.takeIf { it.isNotEmpty() } + fun getTypeIdFromCursorRow(row: Array): Int = row[0] as Int + fun getTargetFromCursorRow(row: Array): String? = (row.getOrNull(1) as? String)?.takeIf { it.isNotEmpty() } + fun getLangFromCursorRow(row: Array): String = row[2] as String + fun getColorFromCursorRow(row: Array): String? = (row.getOrNull(3) as? String)?.takeIf { it.isNotEmpty() } + fun getSeverityFromCursorRow(row: Array): Int = row[4] as Int + fun getNoteworthyFromCursorRow(row: Array): Long = row[5] as Long + fun getExtraFromCursorRow(row: Array): String? = (row.getOrNull(6) as? String)?.takeIf { it.isNotEmpty() } - fun getTargetFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow("target")) - fun getLangFromCursorRow(cursor: Cursor): String = cursor.getString(cursor.getColumnIndexOrThrow("lang")) - fun getColorFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow("color")) - fun getSeverityFromCursorRow(cursor: Cursor): Int = cursor.getInt(cursor.getColumnIndexOrThrow("severity")) - fun getNoteworthyFromCursorRow(cursor: Cursor): Long = cursor.getLong(cursor.getColumnIndexOrThrow("noteworthy")) - fun getExtraFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow("extra")) + fun getTypeIdFromCursorRow(cursor: Cursor): Int = cursor.getInt(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_TYPE)) + fun getTargetFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_TARGET)) + fun getLangFromCursorRow(cursor: Cursor): String = cursor.getString(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_LANG)) + fun getColorFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_COLOR)) + fun getSeverityFromCursorRow(cursor: Cursor): Int = cursor.getInt(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_SEVERITY)) + fun getNoteworthyFromCursorRow(cursor: Cursor): Long = cursor.getLong(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_NOTEWORTHY)) + fun getExtraFromCursorRow(cursor: Cursor): String? = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(FeedConfigColumns.T_NEWS_FEED_CONFIG_K_EXTRA)) } } \ No newline at end of file diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt index 64fc7c90..9304fd00 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/instagram/InstagramNewsFeedConfig.kt @@ -8,7 +8,7 @@ import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.put import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.provider.config.news.NewsFeedConfig -import org.mtransit.android.commons.provider.config.news.rss.RSSNewsFeedConfig +import org.mtransit.android.commons.provider.config.news.NewsType import java.lang.IllegalStateException data class InstagramNewsFeedConfig( @@ -46,6 +46,7 @@ data class InstagramNewsFeedConfig( override fun toCursorRow(): Array { return makeCursorRow( + type = NewsType.INSTAGRAM, extra = Json.encodeToString( buildJsonObject { put("username", username) diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt index 1efbd51a..f2cd170a 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/rss/RSSNewsFeedConfig.kt @@ -10,6 +10,7 @@ import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.put import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.provider.config.news.NewsFeedConfig +import org.mtransit.android.commons.provider.config.news.NewsType import java.lang.IllegalStateException data class RSSNewsFeedConfig( @@ -69,6 +70,7 @@ data class RSSNewsFeedConfig( @Suppress("SimplifyBooleanWithConstants") override fun toCursorRow(): Array { return makeCursorRow( + type = NewsType.RSS, extra = Json.encodeToString( buildJsonObject { put("url", url) diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt index 9483a267..75a13497 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/twitter/TwitterNewsFeedConfig.kt @@ -9,6 +9,7 @@ import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.put import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.provider.config.news.NewsFeedConfig +import org.mtransit.android.commons.provider.config.news.NewsType import java.lang.IllegalStateException data class TwitterNewsFeedConfig( @@ -48,6 +49,7 @@ data class TwitterNewsFeedConfig( override fun toCursorRow(): Array { return makeCursorRow( + type = NewsType.TWITTER, extra = Json.encodeToString( buildJsonObject { put("username", username) diff --git a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt index 29b54758..3d4ff3ef 100644 --- a/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt +++ b/src/main/java/org/mtransit/android/commons/provider/config/news/youtube/YouTubeNewsFeedConfig.kt @@ -9,7 +9,7 @@ import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonPrimitive import org.mtransit.android.commons.LocaleUtils import org.mtransit.android.commons.provider.config.news.NewsFeedConfig -import org.mtransit.android.commons.provider.config.news.rss.RSSNewsFeedConfig +import org.mtransit.android.commons.provider.config.news.NewsType import java.lang.IllegalStateException data class YouTubeNewsFeedConfig( @@ -53,6 +53,7 @@ data class YouTubeNewsFeedConfig( override fun toCursorRow(): Array { return makeCursorRow( + type = NewsType.YOUTUBE, extra = Json.encodeToString( buildJsonObject { put("authorUrl", authorUrl)