Skip to content

Commit

Permalink
Merge branch 'main' into feat/language
Browse files Browse the repository at this point in the history
  • Loading branch information
nqmgaming authored Nov 30, 2024
2 parents b3c4549 + c6f7b0d commit 484dde7
Show file tree
Hide file tree
Showing 92 changed files with 725 additions and 376 deletions.
3 changes: 1 addition & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ android {
localProperties.getProperty("REWARD_ADS_ID") ?: "ca-app-pub-5725743620724195/5188260450"
val rewardedInterstitialAdsId: String =
localProperties.getProperty("REWARDED_INTERSTITIAL_ADS_ID")
?: "ca-app-pub-3940256099942544/5354046379"
?: "ca-app-pub-5725743620724195/6760705307"
val oneSignalAppId: String = localProperties.getProperty("ONESIGNAL_APP_ID")
?: "b2f7f966-d8cc-11e4-bed1-df8f05be55ba"
val revenueCatApiKey: String = localProperties.getProperty("REVENUECAT_API_KEY")
Expand Down Expand Up @@ -101,7 +101,6 @@ dependencies {
ksp(libs.androidx.room.compiler)
implementation(libs.compose.charts)


implementation(libs.play.services.ads)

implementation(project(":compose-cardstack"))
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/pwhs/quickmem/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.onesignal.OneSignal
import com.onesignal.debug.LogLevel as OneSignalLogLevel
import com.pwhs.quickmem.core.datastore.AppManager
import com.pwhs.quickmem.core.datastore.TokenManager
import com.pwhs.quickmem.data.dto.notification.TokenRequestDto
import com.pwhs.quickmem.data.dto.notification.DeviceTokenRequestDto
import com.pwhs.quickmem.data.remote.ApiService
import com.revenuecat.purchases.LogLevel as RevenueCatLogLevel
import com.revenuecat.purchases.Purchases
Expand Down Expand Up @@ -78,7 +78,7 @@ class App : Application() {
val accessToken = tokenManager.accessToken.firstOrNull() ?: ""
val userId = appManager.userId.firstOrNull() ?: ""
try {
apiService.sendDeviceToken(accessToken, TokenRequestDto(userId, token))
apiService.sendDeviceToken(accessToken, DeviceTokenRequestDto(userId, token))
Timber.d("Token sent to server successfully.")
} catch (e: Exception) {
Timber.e(e, "Error sending token to server")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.pwhs.quickmem.core.data.enums

enum class CoinAction (val action: String) {
ADD("add"),
SUBTRACT("subtract")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.pwhs.quickmem.core.data.enums

enum class NotificationType(val type: String) {
INVITE_USER_JOIN_CLASS("INVITE_USER_JOIN_CLASS"),
NONE("NONE"),
}
18 changes: 16 additions & 2 deletions app/src/main/java/com/pwhs/quickmem/core/datastore/AppManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import android.util.Patterns
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import com.pwhs.quickmem.util.dataStore
import kotlinx.coroutines.flow.Flow
Expand All @@ -23,6 +24,7 @@ class AppManager(private val context: Context) {
val USER_BIRTHDAY = stringPreferencesKey("USER_BIRTHDAY")
val PUSH_NOTIFICATIONS = booleanPreferencesKey("PUSH_NOTIFICATIONS")
val APP_PUSH_NOTIFICATIONS = booleanPreferencesKey("APP_PUSH_NOTIFICATIONS")
val USER_COINS = intPreferencesKey("USER_COINS")
}

val isFirstRun: Flow<Boolean> = context.dataStore.data
Expand All @@ -41,11 +43,11 @@ class AppManager(private val context: Context) {
.map { preferences ->
preferences[USER_FULL_NAME] ?: ""
}
val userName: Flow<String> = context.dataStore.data
val username: Flow<String> = context.dataStore.data
.map { preferences ->
preferences[USER_NAME] ?: ""
}
val userAvatar: Flow<String> = context.dataStore.data
val userAvatarUrl: Flow<String> = context.dataStore.data
.map { preferences ->
preferences[USER_AVATAR] ?: ""
}
Expand All @@ -72,6 +74,11 @@ class AppManager(private val context: Context) {
preferences[USER_BIRTHDAY] ?: ""
}

val userCoins: Flow<Int> = context.dataStore.data
.map { preferences ->
preferences[USER_COINS] ?: 0
}

suspend fun saveIsFirstRun(isFirstRun: Boolean) {
Timber.d("Saving is first run: $isFirstRun")
context.dataStore.edit { preferences ->
Expand Down Expand Up @@ -150,6 +157,13 @@ class AppManager(private val context: Context) {
}
}

suspend fun saveUserCoins(coins: Int) {
Timber.d("Saving user coins: $coins")
context.dataStore.edit { preferences ->
preferences[USER_COINS] = coins
}
}

suspend fun clearAllData() {
context.dataStore.edit { preferences ->
preferences.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import android.content.Intent
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES
import androidx.core.app.NotificationCompat
import androidx.core.net.toUri
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.pwhs.quickmem.MainActivity
import com.pwhs.quickmem.R
import com.pwhs.quickmem.core.datastore.AppManager
import com.pwhs.quickmem.core.datastore.TokenManager
import com.pwhs.quickmem.data.dto.notification.TokenRequestDto
import com.pwhs.quickmem.data.dto.notification.DeviceTokenRequestDto
import com.pwhs.quickmem.data.remote.ApiService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -42,7 +43,7 @@ class AppFirebaseMessagingService : FirebaseMessagingService() {
val accessToken = tokenManager.accessToken.firstOrNull() ?: ""
val userId = appManager.userId.firstOrNull() ?: ""
try {
apiService.sendDeviceToken(accessToken, TokenRequestDto(userId, token))
apiService.sendDeviceToken(accessToken, DeviceTokenRequestDto(userId, token))
Timber.d("Token sent to server successfully.")
} catch (e: Exception) {
Timber.e(e, "Error sending token to server")
Expand All @@ -54,23 +55,38 @@ class AppFirebaseMessagingService : FirebaseMessagingService() {

override fun onMessageReceived(remoteMessage: RemoteMessage) {
Timber.d("From: ${remoteMessage.from}")
remoteMessage.notification?.title?.let { Timber.d("Notification Title: $it") }
remoteMessage.notification?.body?.let { Timber.d("Notification Body: $it") }
remoteMessage.data.isNotEmpty()
.let { Timber.d("Message data payload: ${remoteMessage.data}") }
CoroutineScope(Dispatchers.IO).launch {
val isPushNotificationsEnabled = appManager.pushNotifications.firstOrNull() ?: false
if (isPushNotificationsEnabled) {
remoteMessage.notification?.let {
showNotification(it.title, it.body)
showNotification(it.title, it.body, remoteMessage.data)
}
}
}
}

private fun showNotification(title: String?, body: String?) {
private fun showNotification(title: String?, body: String?, data: Map<String, String>) {
val channelId = "QuickMem Channel"
val notificationId = 0

val intent = Intent(this, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val notificationType = data["notificationType"]
val classCode = data["code"]

val intent = if (notificationType == "INVITE_USER_JOIN_CLASS" && classCode != null) {
Intent(
Intent.ACTION_VIEW,
"quickmem://join/class?code=$classCode".toUri()
)
} else {
Intent(this, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
}

val pendingIntent = PendingIntent.getActivity(
this,
0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ data class AuthResponseDto(
val provider: String? = null,
@SerializedName("isVerified")
val isVerified: Boolean? = null,
@SerializedName("coin")
val coin: Int? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ data class GetUserProfileResponseDto(
val avatarUrl: String,
@SerializedName("role")
val role: String,
@SerializedName("coin")
val coin: Int,
@SerializedName("createdAt")
val createdAt: String,
@SerializedName("updatedAt")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.pwhs.quickmem.data.dto.notification

import com.google.gson.annotations.SerializedName

data class TokenRequestDto(
data class DeviceTokenRequestDto(
@SerializedName("userId")
val userId: String,
@SerializedName("deviceToken")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.pwhs.quickmem.data.dto.notification

import com.google.gson.annotations.SerializedName
import com.pwhs.quickmem.core.data.enums.NotificationType

data class GetNotificationResponseDto(
@SerializedName("id")
Expand All @@ -13,6 +14,10 @@ data class GetNotificationResponseDto(
val userId: String,
@SerializedName("isRead")
val isRead: Boolean,
@SerializedName("notificationType")
val notificationType: NotificationType? = NotificationType.NONE,
@SerializedName("data")
val data: NotificationDataDto? = null,
@SerializedName("createdAt")
val createdAt: String,
@SerializedName("updatedAt")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.pwhs.quickmem.data.dto.notification

import com.google.gson.annotations.SerializedName

data class NotificationDataDto(
@SerializedName("id")
val id: String? = null,
@SerializedName("code")
val code: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.pwhs.quickmem.data.dto.user

import com.google.gson.annotations.SerializedName

data class UpdateCoinRequestDto(
@SerializedName("userId")
val userId: String,
@SerializedName("coin")
val coin: Int,
@SerializedName("action")
val action: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.pwhs.quickmem.data.dto.user

import com.google.gson.annotations.SerializedName

data class UpdateCoinResponseDto(
@SerializedName("message")
val message: String,
@SerializedName("coinAction")
val coinAction: String,
@SerializedName("coins")
val coins: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ fun GetUserProfileResponseDto.toModel() = GetUserProfileResponseModel(
username = username,
avatarUrl = avatarUrl,
createdAt = createdAt,
updatedAt = updatedAt
updatedAt = updatedAt,
coin = coin
)

fun GetUserProfileResponseModel.toDto() = GetUserProfileResponseDto(
Expand All @@ -22,5 +23,6 @@ fun GetUserProfileResponseModel.toDto() = GetUserProfileResponseDto(
username = username,
avatarUrl = avatarUrl,
createdAt = createdAt,
updatedAt = updatedAt
updatedAt = updatedAt,
coin = coin
)
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ fun GetNotificationResponseDto.toModel() = GetNotificationResponseModel(
userId = userId,
isRead = isRead,
createdAt = createdAt,
updatedAt = updatedAt
updatedAt = updatedAt,
notificationType = notificationType,
data = data?.toModel()
)

fun GetNotificationResponseModel.toDto() = GetNotificationResponseDto(
Expand All @@ -20,5 +22,7 @@ fun GetNotificationResponseModel.toDto() = GetNotificationResponseDto(
userId = userId,
isRead = isRead,
createdAt = createdAt,
updatedAt = updatedAt
updatedAt = updatedAt,
notificationType = notificationType,
data = data?.toDto()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.pwhs.quickmem.data.mapper.notification

import com.pwhs.quickmem.data.dto.notification.NotificationDataDto
import com.pwhs.quickmem.domain.model.notification.NotificationDataModel

fun NotificationDataDto.toModel() = NotificationDataModel(
id = id,
code = code
)

fun NotificationDataModel.toDto() = NotificationDataDto(
id = id,
code = code
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.pwhs.quickmem.data.mapper.user

import com.pwhs.quickmem.data.dto.user.UpdateCoinRequestDto
import com.pwhs.quickmem.domain.model.users.UpdateCoinRequestModel

fun UpdateCoinRequestDto.toModel() = UpdateCoinRequestModel(
userId = userId,
coin = coin,
action = action
)

fun UpdateCoinRequestModel.toDto() = UpdateCoinRequestDto(
userId = userId,
coin = coin,
action = action
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.pwhs.quickmem.data.mapper.user

import com.pwhs.quickmem.data.dto.user.UpdateCoinResponseDto
import com.pwhs.quickmem.domain.model.users.UpdateCoinResponseModel

fun UpdateCoinResponseDto.toModel() = UpdateCoinResponseModel(
message = message,
coinAction = coinAction,
coins = coins
)

fun UpdateCoinResponseModel.toDto() = UpdateCoinResponseDto(
message = message,
coinAction = coinAction,
coins = coins
)
12 changes: 10 additions & 2 deletions app/src/main/java/com/pwhs/quickmem/data/remote/ApiService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import com.pwhs.quickmem.data.dto.folder.UpdateFolderRequestDto
import com.pwhs.quickmem.data.dto.folder.UpdateFolderResponseDto
import com.pwhs.quickmem.data.dto.notification.GetNotificationResponseDto
import com.pwhs.quickmem.data.dto.notification.MarkNotificationReadRequestDto
import com.pwhs.quickmem.data.dto.notification.TokenRequestDto
import com.pwhs.quickmem.data.dto.notification.DeviceTokenRequestDto
import com.pwhs.quickmem.data.dto.flashcard.WriteStatusFlashCardDto
import com.pwhs.quickmem.data.dto.streak.GetStreakDto
import com.pwhs.quickmem.data.dto.streak.GetTopStreakResponseDto
Expand All @@ -81,6 +81,8 @@ import com.pwhs.quickmem.data.dto.subject.GetTop5SubjectResponseDto
import com.pwhs.quickmem.data.dto.upload.DeleteImageDto
import com.pwhs.quickmem.data.dto.upload.UploadImageResponseDto
import com.pwhs.quickmem.data.dto.user.SearchUserResponseDto
import com.pwhs.quickmem.data.dto.user.UpdateCoinRequestDto
import com.pwhs.quickmem.data.dto.user.UpdateCoinResponseDto
import com.pwhs.quickmem.data.dto.user.UserDetailResponseDto
import okhttp3.MultipartBody
import retrofit2.Response
Expand Down Expand Up @@ -183,6 +185,12 @@ interface ApiService {
@Query("page") page: Int?
): List<SearchUserResponseDto>

@POST("auth/coin")
suspend fun updateCoin(
@Header("Authorization") token: String,
@Body request: UpdateCoinRequestDto
): UpdateCoinResponseDto

// Upload
@Multipart
@POST("upload")
Expand Down Expand Up @@ -564,7 +572,7 @@ interface ApiService {
@POST("notifications/register")
suspend fun sendDeviceToken(
@Header("Authorization") authorization: String,
@Body tokenRequest: TokenRequestDto
@Body tokenRequest: DeviceTokenRequestDto
): Response<Unit>

@GET("notifications/user/{id}")
Expand Down
Loading

0 comments on commit 484dde7

Please sign in to comment.