Skip to content

Implement Notifications #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ android {
defaultConfig {
applicationId "com.cornellappdev.volume"
minSdk 27
targetSdk 32
targetSdk 33
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("String", "PROD_ENDPOINT", secretsProperties['PROD_ENDPOINT'])
buildConfigField("String", "DEV_ENDPOINT", secretsProperties['DEV_ENDPOINT'])
buildConfigField("String", "FEEDBACK_FORM", secretsProperties['FEEDBACK_FORM'])
buildConfigField("String", "WEBSITE", secretsProperties['WEBSITE'])

Expand All @@ -39,9 +37,11 @@ android {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
resValue("bool", "FIREBASE_ANALYTICS_DEACTIVATED", "false")
buildConfigField("String", "ENDPOINT", secretsProperties['PROD_ENDPOINT'])
}
debug {
resValue("bool", "FIREBASE_ANALYTICS_DEACTIVATED", "true")
buildConfigField("String", "ENDPOINT", secretsProperties['DEV_ENDPOINT'])
}
}

Expand Down Expand Up @@ -107,11 +107,12 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'

// Firebase
implementation platform('com.google.firebase:firebase-bom:27.0.0')
implementation platform('com.google.firebase:firebase-bom:31.0.2')
implementation 'com.google.firebase:firebase-inappmessaging-display-ktx'
implementation 'com.vmadalin:easypermissions-ktx:1.0.0'
implementation 'com.google.accompanist:accompanist-permissions:0.27.0'
implementation 'com.google.firebase:firebase-messaging-ktx'
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-installations:17.0.2'

// Accompanist
implementation 'com.google.accompanist:accompanist-pager:0.26.2-beta'
Expand Down
17 changes: 16 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application
android:name=".VolumeApplication"
Expand All @@ -13,6 +14,10 @@
android:supportsRtl="true"
android:theme="@style/Theme.Volumeandroidrevamp">

<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />

<meta-data
android:name="firebase_analytics_collection_deactivated"
android:value="@bool/FIREBASE_ANALYTICS_DEACTIVATED" />
Expand All @@ -27,7 +32,6 @@

<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

Expand All @@ -46,6 +50,17 @@
android:host="weekly_debrief"
android:scheme="volume" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="open_magazine"
android:scheme="volume" />
</intent-filter>
</activity>

<service
Expand Down
13 changes: 12 additions & 1 deletion app/src/main/java/com/cornellappdev/volume/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.cornellappdev.volume

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
Expand All @@ -18,11 +21,19 @@ class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val onboardingCompleted = runBlocking {
return@runBlocking userPreferences.fetchOnboardingCompleted()
}

val channelId = getString((R.string.default_notification_channel_id))
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(
NotificationChannel(
channelId,
packageName,
NotificationManager.IMPORTANCE_DEFAULT
)
)

setContent {
MaterialTheme(
colors = LightColors,
Expand Down
16 changes: 15 additions & 1 deletion app/src/main/java/com/cornellappdev/volume/data/models/Social.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.cornellappdev.volume.data.models

import com.cornellappdev.volume.R

/**
* Model class for Socials on Volume
*
Expand All @@ -9,4 +11,16 @@ package com.cornellappdev.volume.data.models
data class Social(
val social: String,
val url: String
)
) {
companion object {
val formattedSocialNameMap = mapOf(
"insta" to "Instagram",
"facebook" to "Facebook",
"linkedin" to "LinkedIn",
"twitter" to "Twitter",
"youtube" to "YouTube"
)
val socialLogoMap =
mapOf("Instagram" to R.drawable.ic_instagram, "Facebook" to R.drawable.ic_facebook)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ class UserPreferencesRepository @Inject constructor(
}
}

suspend fun updateNotificationFlowStatus(value: Boolean) {
userPreferencesStore.updateData { currentPreferences ->
currentPreferences.toBuilder().setNotificationFlowCompleted(value).build()
}
}

suspend fun addBookmarkedArticle(articleId: String) {
userPreferencesStore.updateData { currentPreferences ->
val currentBookmarks = currentPreferences.bookmarkedArticlesList.toHashSet()
Expand Down Expand Up @@ -78,4 +84,7 @@ class UserPreferencesRepository @Inject constructor(

suspend fun fetchShoutoutCount(articleId: String): Int =
userPreferencesFlow.first().shoutoutMap.getOrDefault(articleId, 0)

suspend fun fetchNotificationFlowStatus(): Boolean =
userPreferencesFlow.first().notificationFlowCompleted
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
object NetworkModule {

private const val ENDPOINT = BuildConfig.DEV_ENDPOINT
private const val ENDPOINT = BuildConfig.ENDPOINT

@Singleton
@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
Expand Down Expand Up @@ -51,6 +52,9 @@ fun TabbedNavigationSetup(onboardingCompleted: Boolean) {
Routes.BOOKMARKS.route -> {
showBottomBar.value = true
}
Routes.SETTINGS.route -> {
showBottomBar.value = false
}
Routes.ABOUT_US.route -> {
showBottomBar.value = false
}
Expand Down Expand Up @@ -86,6 +90,7 @@ fun TabbedNavigationSetup(onboardingCompleted: Boolean) {
modifier = Modifier.padding(innerPadding),
isOnboardingCompleted = onboardingCompleted,
navController = navController,
showBottomBar = showBottomBar
)
}
}
Expand All @@ -106,17 +111,20 @@ fun BottomNavigationBar(navController: NavHostController, tabItems: List<Navigat
BottomNavigationItem(
icon = {
Icon(
painter = painterResource(id = if (currentRoute == item.route) item.selectedIconId else item.unselectedIconId),
painter = painterResource(
id = if (item.selectedRoutes.contains(currentRoute)) item.selectedIconId else item.unselectedIconId
),
contentDescription = item.title
)
},
label = { Text(text = item.title, overflow = TextOverflow.Ellipsis, maxLines = 1) },
selectedContentColor = VolumeOrange,
unselectedContentColor = DarkGray,
alwaysShowLabel = true,
selected = currentRoute == item.route,
selected = item.selectedRoutes.contains(currentRoute),
onClick = {
if (currentRoute != item.route) {
FirstTimeShown.firstTimeShown = false
navController.navigate(item.route)
}
}
Expand All @@ -131,6 +139,7 @@ private fun MainScreenNavigationConfigurations(
modifier: Modifier = Modifier,
navController: NavHostController,
isOnboardingCompleted: Boolean,
showBottomBar: MutableState<Boolean>,
) {
// The starting destination switches to onboarding if it isn't completed.
AnimatedNavHost(
Expand All @@ -152,8 +161,11 @@ private fun MainScreenNavigationConfigurations(
}) {
HomeScreen(
onArticleClick = { article, navigationSource ->
FirstTimeShown.firstTimeShown = false
navController.navigate("${Routes.OPEN_ARTICLE.route}/${article.id}/${navigationSource.name}")
})
},
showBottomBar = showBottomBar,
)
}
composable(route = Routes.WEEKLY_DEBRIEF.route, deepLinks = listOf(
navDeepLink { uriPattern = "volume://${Routes.WEEKLY_DEBRIEF.route}" }
Expand Down Expand Up @@ -218,6 +230,22 @@ private fun MainScreenNavigationConfigurations(
)
}
composable(Routes.MAGAZINES.route) {}
composable(
route = "${Routes.OPEN_MAGAZINE.route}/{magazineId}/{navigationSourceName}",
deepLinks = listOf(
navDeepLink { uriPattern = "volume://${Routes.OPEN_MAGAZINE.route}/{magazineId}" }
),
enterTransition = {
fadeIn(
initialAlpha = 0f,
animationSpec = tween(durationMillis = 1500)
)
},
exitTransition = {
fadeOut(
animationSpec = tween(durationMillis = 1500)
)
}) {}
composable(Routes.PUBLICATIONS.route) {
PublicationsScreen(
onPublicationClick =
Expand All @@ -227,7 +255,8 @@ private fun MainScreenNavigationConfigurations(
)

}
composable(Routes.BOOKMARKS.route,
composable(
Routes.BOOKMARKS.route,
enterTransition = {
fadeIn(
initialAlpha = 0f,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,54 @@ import com.cornellappdev.volume.R
* @property unselectedIconId represents the resource id number for the tab icon when not selected
* @property selectedIconId represents the resource id number for the tab icon when selected
* @property title title of tab
* @property selectedRoutes represents the routes the tab should be considered selected for
*/
sealed class NavigationItem(
val route: String,
val unselectedIconId: Int,
val selectedIconId: Int,
val title: String
val title: String,
val selectedRoutes: Set<String>
) {
object Home : NavigationItem(
Routes.HOME.route,
R.drawable.ic_volume_bars_gray,
R.drawable.ic_volume_bars_orange,
"For You"
route = Routes.HOME.route,
unselectedIconId = R.drawable.ic_volume_bars_gray,
selectedIconId = R.drawable.ic_volume_bars_orange,
title = "For You",
selectedRoutes = setOf(Routes.HOME.route, Routes.WEEKLY_DEBRIEF.route)
)

object Magazines : NavigationItem(
Routes.MAGAZINES.route,
R.drawable.ic_magazine_icon_selected,
R.drawable.ic_magazine_icon_unselected,
"Magazines"
route = Routes.MAGAZINES.route,
unselectedIconId = R.drawable.ic_magazine_icon_unselected,
selectedIconId = R.drawable.ic_magazine_icon_selected,
title = "Magazines",
selectedRoutes = setOf(Routes.MAGAZINES.route)
)

object Publications : NavigationItem(
Routes.PUBLICATIONS.route,
R.drawable.ic_publications_icon_selected,
R.drawable.ic_publications_icon_unselected,
"Publications"
route = Routes.PUBLICATIONS.route,
unselectedIconId = R.drawable.ic_publications_icon_unselected,
selectedIconId = R.drawable.ic_publications_icon_selected,
title = "Publications",
selectedRoutes = setOf(
Routes.PUBLICATIONS.route,
"${Routes.INDIVIDUAL_PUBLICATION.route}/{publicationSlug}"
)
)

object Bookmarks :
NavigationItem(
Routes.BOOKMARKS.route,
R.drawable.ic_bookmark_gray,
R.drawable.ic_bookmark_orange,
"Saved"
)
object Bookmarks : NavigationItem(
route = Routes.BOOKMARKS.route,
unselectedIconId = R.drawable.ic_bookmark_gray,
selectedIconId = R.drawable.ic_bookmark_orange,
title = "Bookmarks",
selectedRoutes = setOf(Routes.BOOKMARKS.route)
)

companion object {
val bottomNavTabList = listOf(
Home,
Magazines,
// Magazines,
Publications,
Bookmarks
)
Expand All @@ -75,6 +83,7 @@ enum class Routes(override var route: String) : NavUnit {
ONBOARDING("onboarding"),
INDIVIDUAL_PUBLICATION("individual"),
OPEN_ARTICLE("open_article"),
OPEN_MAGAZINE("open_magazine"),
SETTINGS("settings"),
ABOUT_US("about_us"),
WEEKLY_DEBRIEF("weekly_debrief")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import com.cornellappdev.volume.ui.theme.*
*/
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun CreateHorizontalArticleRow(
fun CreateArticleRow(
article: Article,
isABookmarkedArticle: Boolean = false,
onClick: (Article) -> Unit
Expand Down
Loading