Skip to content

Commit 1b814fe

Browse files
authored
Merge pull request #78 from ricknout/feature/news-feed
Add news feed
2 parents 0d3b2f3 + 6a60df3 commit 1b814fe

File tree

63 files changed

+972
-47
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+972
-47
lines changed

Diff for: README.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55

66
Rugby Ranker is a **work-in-progess** Android app for viewing and predicting the latest World Rugby rankings.
77

8-
It displays the latest international rankings, live scores, fixtures and results and makes use of the [World Rugby 'Points Exchange' system](https://www.world.rugby/rankings/explanation) in order to predict changes in team positions and points.
8+
It displays the latest international rankings, live scores, fixtures, results and news. It makes use of the [World Rugby 'Points Exchange' system](https://www.world.rugby/rankings/explanation) in order to predict changes in team positions and points.
99

1010
<br>
1111

12-
<p align="center">
13-
<img alt="Rugby Ranker Demo" src="/art/demo.gif" width="320" />
14-
</p>
12+
| Rankings | Predict | Predictions | Live |
13+
| ------ | ----- | ------ | ----- |
14+
| ![Rankings](/art/screenshots/screenshot-1.png) | ![Predict](/art/screenshots/screenshot-2.png) | ![Predictions](/art/screenshots/screenshot-3.png) | ![Live](/art/screenshots/screenshot-4.png) |
15+
16+
| Fixtures | Results | News | Info |
17+
| ------ | ----- | ------ | ----- |
18+
| ![Fixtures](/art/screenshots/screenshot-5.png) | ![Results](/art/screenshots/screenshot-6.png) | ![News](/art/screenshots/screenshot-7.png) | ![Info](/art/screenshots/screenshot-8.png) |
1519

1620
<p align="center">
1721
<a href="https://play.google.com/store/apps/details?id=com.ricknout.rugbyranker" target="_blank">

Diff for: app/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ dependencies {
5252
implementation project(':teams')
5353
implementation project(':matches')
5454
implementation project(':live')
55+
implementation project(':news')
5556
implementation project(':info')
5657
implementation project(':theme')
5758
implementation deps.androidX.viewPager2

Diff for: app/proguard-rules.pro

+10
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,13 @@
7878
-keepclassmembernames class kotlinx.** {
7979
volatile <fields>;
8080
}
81+
82+
## Glide
83+
## http://bumptech.github.io/glide/doc/download-setup.html#proguard
84+
85+
-keep public class * implements com.bumptech.glide.module.GlideModule
86+
-keep public class * extends com.bumptech.glide.module.AppGlideModule
87+
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
88+
**[] $VALUES;
89+
public *;
90+
}

Diff for: app/src/main/AndroidManifest.xml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package="com.ricknout.rugbyranker">
66

77
<uses-permission android:name="android.permission.INTERNET" />
8+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
89

910
<application
1011
android:allowBackup="true"

Diff for: app/src/main/java/com/ricknout/rugbyranker/MainActivity.kt

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import com.ricknout.rugbyranker.matches.ui.MensCompleteMatchesViewModel
1313
import com.ricknout.rugbyranker.matches.ui.MensUnplayedMatchesViewModel
1414
import com.ricknout.rugbyranker.matches.ui.WomensCompleteMatchesViewModel
1515
import com.ricknout.rugbyranker.matches.ui.WomensUnplayedMatchesViewModel
16+
import com.ricknout.rugbyranker.news.ui.NewsViewModel
1617
import com.ricknout.rugbyranker.rankings.ui.MensRankingsViewModel
1718
import com.ricknout.rugbyranker.rankings.ui.WomensRankingsViewModel
1819
import com.ricknout.rugbyranker.ui.MensViewModel
@@ -27,6 +28,7 @@ class MainActivity : DaggerAndroidXAppCompatActivity(R.layout.activity_main) {
2728

2829
private val mensViewModel: MensViewModel by viewModels { viewModelFactory }
2930
private val womensViewModel: WomensViewModel by viewModels { viewModelFactory }
31+
private val newsViewModel: NewsViewModel by viewModels { viewModelFactory }
3032
private val infoViewModel: InfoViewModel by viewModels { viewModelFactory }
3133
private val mensRankingsViewModel: MensRankingsViewModel by viewModels { viewModelFactory }
3234
private val womensRankingsViewModel: WomensRankingsViewModel by viewModels { viewModelFactory }
@@ -61,6 +63,7 @@ class MainActivity : DaggerAndroidXAppCompatActivity(R.layout.activity_main) {
6163
womensUnplayedMatchesViewModel.scrollToTop()
6264
womensCompleteMatchesViewModel.scrollToTop()
6365
}
66+
R.id.newsFragment -> newsViewModel.scrollToTop()
6467
R.id.infoNavGraph -> infoViewModel.scrollToTop()
6568
}
6669
}

Diff for: app/src/main/java/com/ricknout/rugbyranker/db/RugbyRankerDb.kt

+11-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,21 @@ import androidx.room.RoomDatabase
55
import androidx.room.TypeConverters
66
import com.ricknout.rugbyranker.matches.db.WorldRugbyMatchDao
77
import com.ricknout.rugbyranker.matches.vo.WorldRugbyMatch
8+
import com.ricknout.rugbyranker.news.db.WorldRugbyNewsDao
9+
import com.ricknout.rugbyranker.news.vo.WorldRugbyArticle
810
import com.ricknout.rugbyranker.rankings.db.WorldRugbyRankingDao
911
import com.ricknout.rugbyranker.rankings.vo.WorldRugbyRanking
1012
import com.ricknout.rugbyranker.teams.db.WorldRugbyTeamDao
1113
import com.ricknout.rugbyranker.teams.vo.WorldRugbyTeam
1214

1315
@Database(
14-
entities = [WorldRugbyRanking::class, WorldRugbyMatch::class, WorldRugbyTeam::class],
15-
version = 3,
16+
entities = [
17+
WorldRugbyRanking::class,
18+
WorldRugbyMatch::class,
19+
WorldRugbyTeam::class,
20+
WorldRugbyArticle::class
21+
],
22+
version = 4,
1623
exportSchema = false
1724
)
1825
@TypeConverters(RugbyRankerTypeConverters::class)
@@ -24,6 +31,8 @@ abstract class RugbyRankerDb : RoomDatabase() {
2431

2532
abstract fun worldRugbyTeamDao(): WorldRugbyTeamDao
2633

34+
abstract fun worldRugbyNewsDao(): WorldRugbyNewsDao
35+
2736
companion object {
2837
const val DATABASE_NAME = "rugby_ranker.db"
2938
}

Diff for: app/src/main/java/com/ricknout/rugbyranker/db/RugbyRankerMigrations.kt

+6
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,10 @@ object RugbyRankerMigrations {
2020
database.execSQL("CREATE TABLE world_rugby_teams (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, abbreviation TEXT NOT NULL, sport INTEGER NOT NULL)")
2121
}
2222
}
23+
24+
val MIGRATION_3_4 = object : Migration(3, 4) {
25+
override fun migrate(database: SupportSQLiteDatabase) {
26+
database.execSQL("CREATE TABLE world_rugby_articles (id INTEGER PRIMARY KEY NOT NULL, title TEXT NOT NULL, subtitle TEXT, summary TEXT NOT NULL, imageUrl TEXT, articleUrl TEXT NOT NULL, timeMillis INTEGER NOT NULL, language TEXT NOT NULL)")
27+
}
28+
}
2329
}

Diff for: app/src/main/java/com/ricknout/rugbyranker/di/AppModule.kt

+50-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import com.ricknout.rugbyranker.matches.db.WorldRugbyMatchDao
1212
import com.ricknout.rugbyranker.matches.prefs.MatchesSharedPreferences
1313
import com.ricknout.rugbyranker.matches.repository.MatchesRepository
1414
import com.ricknout.rugbyranker.matches.work.MatchesWorkManager
15+
import com.ricknout.rugbyranker.news.db.WorldRugbyNewsDao
16+
import com.ricknout.rugbyranker.news.prefs.NewsSharedPreferences
17+
import com.ricknout.rugbyranker.news.repository.NewsRepository
18+
import com.ricknout.rugbyranker.news.work.NewsWorkManager
1519
import com.ricknout.rugbyranker.rankings.db.WorldRugbyRankingDao
1620
import com.ricknout.rugbyranker.rankings.prefs.RankingsSharedPreferences
1721
import com.ricknout.rugbyranker.rankings.repository.RankingsRepository
@@ -23,7 +27,9 @@ import com.ricknout.rugbyranker.theme.prefs.ThemeSharedPreferences
2327
import com.ricknout.rugbyranker.theme.repository.ThemeRepository
2428
import dagger.Module
2529
import dagger.Provides
30+
import java.util.concurrent.TimeUnit
2631
import javax.inject.Singleton
32+
import okhttp3.OkHttpClient
2733
import retrofit2.Retrofit
2834
import retrofit2.converter.gson.GsonConverterFactory
2935
import retrofit2.create
@@ -39,8 +45,18 @@ class AppModule {
3945

4046
@Provides
4147
@Singleton
42-
fun provideRetrofit(): Retrofit {
48+
fun provideOkHttpClient(): OkHttpClient {
49+
return OkHttpClient.Builder()
50+
.connectTimeout(1, TimeUnit.MINUTES)
51+
.readTimeout(1, TimeUnit.MINUTES)
52+
.build()
53+
}
54+
55+
@Provides
56+
@Singleton
57+
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
4358
return Retrofit.Builder()
59+
.client(okHttpClient)
4460
.addConverterFactory(GsonConverterFactory.create())
4561
.baseUrl(WorldRugbyService.BASE_URL)
4662
.build()
@@ -56,7 +72,11 @@ class AppModule {
5672
@Singleton
5773
fun provideDatabase(context: Context): RugbyRankerDb {
5874
return Room.databaseBuilder(context, RugbyRankerDb::class.java, RugbyRankerDb.DATABASE_NAME)
59-
.addMigrations(RugbyRankerMigrations.MIGRATION_1_2, RugbyRankerMigrations.MIGRATION_2_3)
75+
.addMigrations(
76+
RugbyRankerMigrations.MIGRATION_1_2,
77+
RugbyRankerMigrations.MIGRATION_2_3,
78+
RugbyRankerMigrations.MIGRATION_3_4
79+
)
6080
.build()
6181
}
6282

@@ -78,6 +98,12 @@ class AppModule {
7898
return database.worldRugbyTeamDao()
7999
}
80100

101+
@Provides
102+
@Singleton
103+
fun provideWorldRugbyNewsDao(database: RugbyRankerDb): WorldRugbyNewsDao {
104+
return database.worldRugbyNewsDao()
105+
}
106+
81107
@Provides
82108
@Singleton
83109
fun provideSharedPreferences(context: Context): SharedPreferences {
@@ -102,6 +128,12 @@ class AppModule {
102128
return ThemeSharedPreferences(sharedPreferences)
103129
}
104130

131+
@Provides
132+
@Singleton
133+
fun provideNewsSharedPreferences(sharedPreferences: SharedPreferences): NewsSharedPreferences {
134+
return NewsSharedPreferences(sharedPreferences)
135+
}
136+
105137
@Provides
106138
@Singleton
107139
fun provideRankingsRepository(
@@ -137,6 +169,16 @@ class AppModule {
137169
return TeamsRepository(worldRugbyService, worldRugbyTeamDao)
138170
}
139171

172+
@Provides
173+
@Singleton
174+
fun provideNewsRepository(
175+
worldRugbyService: WorldRugbyService,
176+
worldRugbyNewsDao: WorldRugbyNewsDao,
177+
newsSharedPreferences: NewsSharedPreferences
178+
): NewsRepository {
179+
return NewsRepository(worldRugbyService, worldRugbyNewsDao, newsSharedPreferences)
180+
}
181+
140182
@Provides
141183
@Singleton
142184
fun provideWorkManager(context: Context): WorkManager {
@@ -161,6 +203,12 @@ class AppModule {
161203
return TeamsWorkManager(workManager)
162204
}
163205

206+
@Provides
207+
@Singleton
208+
fun provideNewsWorkManager(workManager: WorkManager): NewsWorkManager {
209+
return NewsWorkManager(workManager)
210+
}
211+
164212
companion object {
165213
private const val SHARED_PREFERENCES_NAME = "rugby_ranker_shared_preferences"
166214
}

Diff for: app/src/main/java/com/ricknout/rugbyranker/di/FragmentBuildersModule.kt

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.ricknout.rugbyranker.di
33
import com.ricknout.rugbyranker.info.ui.InfoFragment
44
import com.ricknout.rugbyranker.live.ui.LiveMatchesFragment
55
import com.ricknout.rugbyranker.matches.ui.MatchesFragment
6+
import com.ricknout.rugbyranker.news.ui.NewsFragment
67
import com.ricknout.rugbyranker.prediction.ui.PredictionBottomSheetDialogFragment
78
import com.ricknout.rugbyranker.rankings.ui.RankingsFragment
89
import com.ricknout.rugbyranker.theme.ui.ThemeDialogFragment
@@ -16,6 +17,9 @@ abstract class FragmentBuildersModule {
1617
@ContributesAndroidInjector
1718
abstract fun contributeSportFragment(): SportFragment
1819

20+
@ContributesAndroidInjector
21+
abstract fun contributeNewsFragment(): NewsFragment
22+
1923
@ContributesAndroidInjector
2024
abstract fun contributeInfoFragment(): InfoFragment
2125

Diff for: app/src/main/java/com/ricknout/rugbyranker/di/ViewModelModule.kt

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.ricknout.rugbyranker.matches.ui.MensCompleteMatchesViewModel
99
import com.ricknout.rugbyranker.matches.ui.MensUnplayedMatchesViewModel
1010
import com.ricknout.rugbyranker.matches.ui.WomensCompleteMatchesViewModel
1111
import com.ricknout.rugbyranker.matches.ui.WomensUnplayedMatchesViewModel
12+
import com.ricknout.rugbyranker.news.ui.NewsViewModel
1213
import com.ricknout.rugbyranker.prediction.ui.MensPredictionViewModel
1314
import com.ricknout.rugbyranker.prediction.ui.WomensPredictionViewModel
1415
import com.ricknout.rugbyranker.rankings.ui.MensRankingsViewModel
@@ -108,4 +109,9 @@ abstract class ViewModelModule {
108109
@IntoMap
109110
@ViewModelKey(WomensTeamsViewModel::class)
110111
abstract fun bindWomensTeamsViewModel(womensTeamsViewModel: WomensTeamsViewModel): ViewModel
112+
113+
@Binds
114+
@IntoMap
115+
@ViewModelKey(NewsViewModel::class)
116+
abstract fun bindNewsViewModel(newsViewModel: NewsViewModel): ViewModel
111117
}

Diff for: app/src/main/java/com/ricknout/rugbyranker/di/WorkerModule.kt

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.ricknout.rugbyranker.matches.work.MensCompleteWorldRugbyMatchesWorker
55
import com.ricknout.rugbyranker.matches.work.MensUnplayedWorldRugbyMatchesWorker
66
import com.ricknout.rugbyranker.matches.work.WomensCompleteWorldRugbyMatchesWorker
77
import com.ricknout.rugbyranker.matches.work.WomensUnplayedWorldRugbyMatchesWorker
8+
import com.ricknout.rugbyranker.news.work.WorldRugbyNewsWorker
89
import com.ricknout.rugbyranker.rankings.work.MensWorldRugbyRankingsWorker
910
import com.ricknout.rugbyranker.rankings.work.WomensWorldRugbyRankingsWorker
1011
import com.ricknout.rugbyranker.teams.work.MensWorldRugbyTeamsWorker
@@ -55,4 +56,9 @@ abstract class WorkerModule {
5556
@IntoMap
5657
@WorkerKey(WomensWorldRugbyTeamsWorker::class)
5758
abstract fun bindWomensWorldRugbyTeamsWorker(womensWorldRugbyTeamsWorker: WomensWorldRugbyTeamsWorker): ListenableWorker
59+
60+
@Binds
61+
@IntoMap
62+
@WorkerKey(WorldRugbyNewsWorker::class)
63+
abstract fun bindWorldRugbyNewsWorker(worldRugbyNewsWorker: WorldRugbyNewsWorker): ListenableWorker
5864
}

Diff for: app/src/main/res/menu/menu_main_navigation.xml

+5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
android:icon="@drawable/sl_gender_female_black_24dp"
1212
android:title="@string/title_womens" />
1313

14+
<item
15+
android:id="@id/newsFragment"
16+
android:icon="@drawable/sl_news_black_24dp"
17+
android:title="@string/title_news" />
18+
1419
<item
1520
android:id="@id/infoNavGraph"
1621
android:icon="@drawable/sl_info_outline_black_24dp"

Diff for: app/src/main/res/navigation/nav_graph_main.xml

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
<argument android:name="sport" android:defaultValue="WOMENS" app:argType="com.ricknout.rugbyranker.core.vo.Sport" />
2323
</fragment>
2424

25+
<fragment
26+
android:id="@+id/newsFragment"
27+
android:name="com.ricknout.rugbyranker.news.ui.NewsFragment"
28+
android:label="NewsFragment"
29+
tools:layout="@layout/fragment_news" />
30+
2531
<include app:graph="@navigation/nav_graph_info" />
2632

2733
<include app:graph="@navigation/nav_graph_prediction" />

Diff for: art/demo.gif

-7.92 MB
Binary file not shown.

Diff for: art/icons.sketch

2.89 KB
Binary file not shown.

Diff for: art/screens.sketch

2.11 MB
Binary file not shown.

Diff for: art/screenshots/screenshot-1.png

247 KB
Loading

Diff for: art/screenshots/screenshot-2.png

134 KB
Loading

Diff for: art/screenshots/screenshot-3.png

230 KB
Loading

Diff for: art/screenshots/screenshot-4.png

131 KB
Loading

Diff for: art/screenshots/screenshot-5.png

213 KB
Loading

Diff for: art/screenshots/screenshot-6.png

246 KB
Loading

Diff for: art/screenshots/screenshot-7.png

679 KB
Loading

Diff for: art/screenshots/screenshot-8.png

85.4 KB
Loading

Diff for: core/build.gradle

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
apply plugin: 'com.android.library'
22
apply plugin: 'kotlin-android'
3+
apply plugin: 'kotlin-kapt'
34

45
android {
56
compileSdkVersion versions.compileSdk
@@ -29,6 +30,7 @@ dependencies {
2930
api deps.androidX.recyclerView
3031
api deps.androidX.swipeRefreshLayout
3132
api deps.androidX.emoji
33+
api deps.androidX.browser
3234
api deps.androidX.lifecycle.extensions
3335
api deps.androidX.room.runtime
3436
api deps.androidX.room.ktx
@@ -40,8 +42,11 @@ dependencies {
4042
api deps.google.dagger.dagger
4143
api deps.google.dagger.android
4244
api deps.google.dagger.androidSupport
43-
api deps.retrofit.retrofit
44-
api deps.retrofit.gsonConverter
45+
api deps.square.okhttp
46+
api deps.square.retrofit.retrofit
47+
api deps.square.retrofit.gsonConverter
48+
api deps.glide.glide
49+
kapt deps.glide.compiler
4550
testImplementation deps.androidX.test.jUnit.ktx
4651
androidTestImplementation deps.androidX.test.core.ktx
4752
androidTestImplementation deps.androidX.test.jUnit.ktx

Diff for: core/src/main/java/com/ricknout/rugbyranker/core/api/WorldRugbyResponses.kt

+18
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,21 @@ data class Naming(
8181
data class WorldRugbyTeamsResponse(
8282
val teams: List<TeamDetail>
8383
)
84+
85+
data class Article(
86+
val id: Long,
87+
val title: String,
88+
val description: String?,
89+
val publishFrom: Long,
90+
val language: String,
91+
val canonicalUrl: String,
92+
val subtitle: String?,
93+
val summary: String?,
94+
val imageUrl: String?,
95+
val onDemandUrl: String?
96+
)
97+
98+
data class WorldRugbyNewsResponse(
99+
val pageInfo: PageInfo,
100+
val content: List<Article>
101+
)

Diff for: core/src/main/java/com/ricknout/rugbyranker/core/api/WorldRugbyService.kt

+10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ interface WorldRugbyService {
2828
@Path("id") id: Long
2929
): WorldRugbyTeamsResponse
3030

31+
@GET("content/worldrugby/text/{lang}")
32+
suspend fun getNews(
33+
@Path("lang") language: String,
34+
@Query("tagNames") tagNames: String,
35+
@Query("page") page: Int,
36+
@Query("pageSize") pageSize: Int
37+
): WorldRugbyNewsResponse
38+
3139
companion object {
3240
const val SPORT_MENS = "mru"
3341
const val SPORT_WOMENS = "wru"
@@ -38,6 +46,8 @@ interface WorldRugbyService {
3846
const val STATE_LIVE_HALF_TIME = "LHT"
3947
const val SORT_ASC = "asc"
4048
const val SORT_DESC = "desc"
49+
const val LANGUAGE_EN = "en"
50+
const val TAG_NAME_NEWS = "News"
4151
const val BASE_URL = "https://cmsapi.pulselive.com/"
4252
}
4353
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.ricknout.rugbyranker.core.glide
2+
3+
import com.bumptech.glide.annotation.GlideModule
4+
import com.bumptech.glide.module.AppGlideModule
5+
6+
@GlideModule
7+
class RugbyRankerGlideModule : AppGlideModule()

0 commit comments

Comments
 (0)