Merge pull request #652 from KotlinGeekDev/oss-push-notifications
Oss push notifications(using UnifiedPush)
This commit is contained in:
@@ -185,6 +185,9 @@ dependencies {
|
|||||||
playImplementation platform('com.google.firebase:firebase-bom:32.3.1')
|
playImplementation platform('com.google.firebase:firebase-bom:32.3.1')
|
||||||
playImplementation 'com.google.firebase:firebase-messaging-ktx'
|
playImplementation 'com.google.firebase:firebase-messaging-ktx'
|
||||||
|
|
||||||
|
//PushNotifications(FDroid)
|
||||||
|
fdroidImplementation 'com.github.UnifiedPush:android-connector:2.2.0'
|
||||||
|
|
||||||
// Charts
|
// Charts
|
||||||
implementation "com.patrykandpatrick.vico:core:${vico_version}"
|
implementation "com.patrykandpatrick.vico:core:${vico_version}"
|
||||||
implementation "com.patrykandpatrick.vico:compose:${vico_version}"
|
implementation "com.patrykandpatrick.vico:compose:${vico_version}"
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name=".Amethyst">
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:exported="true"
|
||||||
|
android:enabled="true"
|
||||||
|
android:name=".service.notifications.PushMessageReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.MESSAGE"/>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.UNREGISTERED"/>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT"/>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED"/>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.REGISTRATION_REFUSED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
package com.vitorpamplona.amethyst.service.notifications
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import com.vitorpamplona.amethyst.Amethyst
|
||||||
|
import org.unifiedpush.android.connector.UnifiedPush
|
||||||
|
|
||||||
|
interface PushDistributorActions {
|
||||||
|
fun getSavedDistributor(): String
|
||||||
|
fun getInstalledDistributors(): List<String>
|
||||||
|
fun saveDistributor(distributor: String)
|
||||||
|
fun removeSavedDistributor()
|
||||||
|
}
|
||||||
|
object PushDistributorHandler : PushDistributorActions {
|
||||||
|
private val appContext = Amethyst.instance.applicationContext
|
||||||
|
private val unifiedPush: UnifiedPush = UnifiedPush
|
||||||
|
|
||||||
|
private var endpointInternal = ""
|
||||||
|
val endpoint = endpointInternal
|
||||||
|
|
||||||
|
fun getSavedEndpoint() = endpoint
|
||||||
|
fun setEndpoint(newEndpoint: String) {
|
||||||
|
endpointInternal = newEndpoint
|
||||||
|
Log.d("PushHandler", "New endpoint saved : $endpointInternal")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeEndpoint() {
|
||||||
|
endpointInternal = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSavedDistributor(): String {
|
||||||
|
return unifiedPush.getDistributor(appContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun savedDistributorExists(): Boolean = getSavedDistributor().isNotEmpty()
|
||||||
|
|
||||||
|
override fun getInstalledDistributors(): List<String> {
|
||||||
|
return unifiedPush.getDistributors(appContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formattedDistributorNames(): List<String> {
|
||||||
|
val distributorsArray = getInstalledDistributors().toTypedArray()
|
||||||
|
val distributorsNameArray = distributorsArray.map {
|
||||||
|
try {
|
||||||
|
val ai = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
appContext.packageManager.getApplicationInfo(
|
||||||
|
it,
|
||||||
|
PackageManager.ApplicationInfoFlags.of(
|
||||||
|
PackageManager.GET_META_DATA.toLong()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
appContext.packageManager.getApplicationInfo(it, 0)
|
||||||
|
}
|
||||||
|
appContext.packageManager.getApplicationLabel(ai)
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
it
|
||||||
|
} as String
|
||||||
|
}.toTypedArray()
|
||||||
|
return distributorsNameArray.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun saveDistributor(distributor: String) {
|
||||||
|
unifiedPush.saveDistributor(appContext, distributor)
|
||||||
|
unifiedPush.registerApp(appContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeSavedDistributor() {
|
||||||
|
unifiedPush.safeRemoveDistributor(appContext)
|
||||||
|
}
|
||||||
|
fun forceRemoveDistributor(context: Context) {
|
||||||
|
unifiedPush.forceRemoveDistributor(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
package com.vitorpamplona.amethyst.service.notifications
|
||||||
|
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import android.util.LruCache
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.vitorpamplona.amethyst.Amethyst
|
||||||
|
import com.vitorpamplona.amethyst.LocalPreferences
|
||||||
|
import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.getOrCreateDMChannel
|
||||||
|
import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.getOrCreateZapChannel
|
||||||
|
import com.vitorpamplona.quartz.events.Event
|
||||||
|
import com.vitorpamplona.quartz.events.GiftWrapEvent
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.unifiedpush.android.connector.MessagingReceiver
|
||||||
|
|
||||||
|
class PushMessageReceiver : MessagingReceiver() {
|
||||||
|
private val TAG = "Amethyst-OSSPushReceiver"
|
||||||
|
private val appContext = Amethyst.instance.applicationContext
|
||||||
|
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||||
|
private val eventCache = LruCache<String, String>(100)
|
||||||
|
private val pushHandler = PushDistributorHandler
|
||||||
|
|
||||||
|
override fun onMessage(context: Context, message: ByteArray, instance: String) {
|
||||||
|
val messageStr = String(message)
|
||||||
|
Log.d(TAG, "New message ${message.decodeToString()} for Instance: $instance")
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
parseMessage(messageStr)?.let {
|
||||||
|
receiveIfNew(it)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.d(TAG, "Message could not be parsed: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun parseMessage(message: String): GiftWrapEvent? {
|
||||||
|
(Event.fromJson(message) as? GiftWrapEvent)?.let {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun receiveIfNew(event: GiftWrapEvent) {
|
||||||
|
if (eventCache.get(event.id) == null) {
|
||||||
|
eventCache.put(event.id, event.id)
|
||||||
|
EventNotificationConsumer(appContext).consume(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
||||||
|
Log.d(TAG, "New endpoint provided:- $endpoint for Instance: $instance")
|
||||||
|
val sanitizedEndpoint = endpoint.dropLast(5)
|
||||||
|
pushHandler.setEndpoint(sanitizedEndpoint)
|
||||||
|
scope.launch(Dispatchers.IO) {
|
||||||
|
RegisterAccounts(LocalPreferences.allSavedAccounts()).go(sanitizedEndpoint)
|
||||||
|
notificationManager().getOrCreateZapChannel(appContext)
|
||||||
|
notificationManager().getOrCreateDMChannel(appContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
val intentData = intent.dataString
|
||||||
|
val intentAction = intent.action.toString()
|
||||||
|
Log.d(TAG, "Intent Data:- $intentData Intent Action: $intentAction")
|
||||||
|
super.onReceive(context, intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRegistrationFailed(context: Context, instance: String) {
|
||||||
|
Log.d(TAG, "Registration failed for Instance: $instance")
|
||||||
|
scope.cancel()
|
||||||
|
pushHandler.forceRemoveDistributor(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUnregistered(context: Context, instance: String) {
|
||||||
|
val removedEndpoint = pushHandler.endpoint
|
||||||
|
Log.d(TAG, "Endpoint: $removedEndpoint removed for Instance: $instance")
|
||||||
|
Log.d(TAG, "App is unregistered. ")
|
||||||
|
pushHandler.forceRemoveDistributor(context)
|
||||||
|
pushHandler.removeEndpoint()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notificationManager(): NotificationManager {
|
||||||
|
return ContextCompat.getSystemService(appContext, NotificationManager::class.java) as NotificationManager
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-1
@@ -1,9 +1,21 @@
|
|||||||
package com.vitorpamplona.amethyst.service.notifications
|
package com.vitorpamplona.amethyst.service.notifications
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.vitorpamplona.amethyst.AccountInfo
|
import com.vitorpamplona.amethyst.AccountInfo
|
||||||
|
|
||||||
object PushNotificationUtils {
|
object PushNotificationUtils {
|
||||||
var hasInit: Boolean = true
|
var hasInit: Boolean = false
|
||||||
|
private val pushHandler = PushDistributorHandler
|
||||||
suspend fun init(accounts: List<AccountInfo>) {
|
suspend fun init(accounts: List<AccountInfo>) {
|
||||||
|
if (hasInit || pushHandler.savedDistributorExists()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (pushHandler.savedDistributorExists()) {
|
||||||
|
RegisterAccounts(accounts).go(pushHandler.getSavedEndpoint())
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.d("Amethyst-OSSPushUtils", "Failed to get endpoint.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import com.halilibo.richtext.markdown.Markdown
|
||||||
|
import com.halilibo.richtext.ui.RichTextStyle
|
||||||
|
import com.halilibo.richtext.ui.material3.Material3RichText
|
||||||
|
import com.halilibo.richtext.ui.resolveDefaults
|
||||||
|
import com.vitorpamplona.amethyst.service.notifications.PushDistributorHandler
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.UserReactionsViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.NotificationViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.HalfPadding
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CustomNotificationScreen(
|
||||||
|
notifFeedViewModel: NotificationViewModel,
|
||||||
|
userReactionsStatsModel: UserReactionsViewModel,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit
|
||||||
|
) {
|
||||||
|
val pushHandler = PushDistributorHandler
|
||||||
|
var distributorPresent by remember {
|
||||||
|
mutableStateOf(pushHandler.savedDistributorExists())
|
||||||
|
}
|
||||||
|
val list = pushHandler.getInstalledDistributors()
|
||||||
|
val readableList = pushHandler.formattedDistributorNames()
|
||||||
|
if (!distributorPresent) {
|
||||||
|
SelectPushDistributor(
|
||||||
|
distrbutorList = readableList.toImmutableList(),
|
||||||
|
onDistributorSelected = { index, name ->
|
||||||
|
val fullDistributorName = list[index]
|
||||||
|
pushHandler.saveDistributor(fullDistributorName)
|
||||||
|
Log.d("Amethyst", "NotificationScreen: Distributor registered.")
|
||||||
|
},
|
||||||
|
onDismiss = {
|
||||||
|
distributorPresent = true
|
||||||
|
Log.d("Amethyst", "NotificationScreen: Distributor dialog dismissed.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val currentDistributor = pushHandler.getSavedDistributor()
|
||||||
|
pushHandler.saveDistributor(currentDistributor)
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationScreen(
|
||||||
|
notifFeedViewModel = notifFeedViewModel,
|
||||||
|
userReactionsStatsModel = userReactionsStatsModel,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SelectPushDistributor(
|
||||||
|
distrbutorList: ImmutableList<String>,
|
||||||
|
onDistributorSelected: (Int, String) -> Unit,
|
||||||
|
onDismiss: () -> Unit
|
||||||
|
) {
|
||||||
|
Dialog(onDismissRequest = onDismiss) {
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.border(
|
||||||
|
width = Dp.Hairline,
|
||||||
|
color = MaterialTheme.colorScheme.background,
|
||||||
|
shape = CircleShape
|
||||||
|
)
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier.align(CenterHorizontally)) {
|
||||||
|
Material3RichText(
|
||||||
|
style = RichTextStyle().resolveDefaults()
|
||||||
|
) {
|
||||||
|
Markdown(content = "### Select a distributor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
distrbutorList.forEachIndexed { index, distributor ->
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
onDistributorSelected(index, distributor)
|
||||||
|
onDismiss()
|
||||||
|
},
|
||||||
|
modifier = HalfPadding.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Material3RichText(
|
||||||
|
style = RichTextStyle().resolveDefaults()
|
||||||
|
) {
|
||||||
|
Markdown(content = distributor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-1
@@ -62,7 +62,12 @@ class RegisterAccounts(
|
|||||||
it.isSuccessful
|
it.isSuccessful
|
||||||
}
|
}
|
||||||
} catch (e: java.lang.Exception) {
|
} catch (e: java.lang.Exception) {
|
||||||
Log.e("FirebaseMsgService", "Unable to register with push server", e)
|
val tag = if (BuildConfig.FLAVOR == "play") {
|
||||||
|
"FirebaseMsgService"
|
||||||
|
} else {
|
||||||
|
"UnifiedPushService"
|
||||||
|
}
|
||||||
|
Log.e(tag, "Unable to register with push server", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChatroomListScreen
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChatroomScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChatroomScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChatroomScreenByAuthor
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChatroomScreenByAuthor
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CommunityScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CommunityScreen
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CustomNotificationScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DiscoverScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DiscoverScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.GeoHashScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.GeoHashScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.HashtagScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.HashtagScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.HiddenUsersScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.HiddenUsersScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.HomeScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.HomeScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.LoadRedirectScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.LoadRedirectScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.NotificationScreen
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ProfileScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ProfileScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.SearchScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.SearchScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.SettingsScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.SettingsScreen
|
||||||
@@ -157,7 +157,7 @@ fun AppNavigation(
|
|||||||
|
|
||||||
Route.Notification.let { route ->
|
Route.Notification.let { route ->
|
||||||
composable(route.route, route.arguments, content = {
|
composable(route.route, route.arguments, content = {
|
||||||
NotificationScreen(
|
CustomNotificationScreen(
|
||||||
notifFeedViewModel = notifFeedViewModel,
|
notifFeedViewModel = notifFeedViewModel,
|
||||||
userReactionsStatsModel = userReactionsStatsModel,
|
userReactionsStatsModel = userReactionsStatsModel,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
|
|||||||
@@ -32,12 +32,9 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
|||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
import com.google.accompanist.permissions.rememberPermissionState
|
import com.google.accompanist.permissions.rememberPermissionState
|
||||||
import com.patrykandpatrick.vico.compose.axis.axisLabelComponent
|
import com.patrykandpatrick.vico.compose.axis.axisLabelComponent
|
||||||
import com.patrykandpatrick.vico.compose.axis.horizontal.bottomAxis
|
|
||||||
import com.patrykandpatrick.vico.compose.axis.horizontal.rememberBottomAxis
|
import com.patrykandpatrick.vico.compose.axis.horizontal.rememberBottomAxis
|
||||||
import com.patrykandpatrick.vico.compose.axis.vertical.endAxis
|
|
||||||
import com.patrykandpatrick.vico.compose.axis.vertical.rememberEndAxis
|
import com.patrykandpatrick.vico.compose.axis.vertical.rememberEndAxis
|
||||||
import com.patrykandpatrick.vico.compose.axis.vertical.rememberStartAxis
|
import com.patrykandpatrick.vico.compose.axis.vertical.rememberStartAxis
|
||||||
import com.patrykandpatrick.vico.compose.axis.vertical.startAxis
|
|
||||||
import com.patrykandpatrick.vico.compose.chart.Chart
|
import com.patrykandpatrick.vico.compose.chart.Chart
|
||||||
import com.patrykandpatrick.vico.compose.chart.line.lineChart
|
import com.patrykandpatrick.vico.compose.chart.line.lineChart
|
||||||
import com.patrykandpatrick.vico.compose.component.shape.shader.fromBrush
|
import com.patrykandpatrick.vico.compose.component.shape.shader.fromBrush
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.UserReactionsViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.NotificationViewModel
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CustomNotificationScreen(
|
||||||
|
notifFeedViewModel: NotificationViewModel,
|
||||||
|
userReactionsStatsModel: UserReactionsViewModel,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit
|
||||||
|
) = NotificationScreen(
|
||||||
|
notifFeedViewModel = notifFeedViewModel,
|
||||||
|
userReactionsStatsModel = userReactionsStatsModel,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
+6
-1
@@ -3,7 +3,12 @@ pluginManagement {
|
|||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url "https://jitpack.io" }
|
maven {
|
||||||
|
url "https://jitpack.io"
|
||||||
|
content {
|
||||||
|
includeModule 'com.github.UnifiedPush', 'android-connector'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
|
|||||||
Reference in New Issue
Block a user