Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fc28e9a
wip added ui for poll func
KrishnaTech6 Jun 25, 2023
163bb27
update: ui for poll create and view
KrishnaTech6 Jun 27, 2023
620bd64
added create poll button in ViewDoubtsFragment
KrishnaTech6 Jun 27, 2023
cd6d5dd
view poll vieholder added , changes in ui
KrishnaTech6 Jun 28, 2023
16cea41
added poll view in main feed with multiple options, poll func WIP
KrishnaTech6 Jun 29, 2023
742efc2
poll vote WIP
KrishnaTech6 Jun 29, 2023
d89d9e4
fix fatal NPE for ViewDoubtViewModel (#73)
PratthamArora Jun 29, 2023
a3f8688
Added icon animations to upvote and downvote icons for Doubts and Ans…
PratthamArora Jun 29, 2023
7bc68f2
added create poll button in ViewDoubtsFragment
KrishnaTech6 Jun 27, 2023
2363a42
view poll vieholder added , changes in ui
KrishnaTech6 Jun 28, 2023
93c8459
added poll view in main feed with multiple options, poll func WIP
KrishnaTech6 Jun 29, 2023
fb31868
changes
KrishnaTech6 Jun 30, 2023
3935a35
changes
KrishnaTech6 Jun 30, 2023
9802125
fix fatal NPE for ViewDoubtViewModel (#73)
PratthamArora Jun 29, 2023
2d8d6b0
automatically close keyboard after search query is submitted (#70)
PratthamArora Jun 29, 2023
28c9cfb
bottom nav icons changes
Jun 25, 2023
aeca466
removed voting usecase from onBind
Jun 25, 2023
26a054f
on pressing back on bottom nav redirects to home frag
Jun 25, 2023
37c66c8
in app notif implemented
Jun 26, 2023
ae71a9e
Home Screen Filter Tags (#77)
Aditya13s Jun 29, 2023
67bbafb
development 0.1.4 merge fixes (#83)
sidsharma2002 Jun 29, 2023
0422c05
setted up year text (#85)
sidsharma2002 Jun 29, 2023
ce6a871
change tag analytics name (#84)
Aditya13s Jun 29, 2023
ec98ead
Badge Feature (#86)
Aditya13s Jul 1, 2023
a11e900
fixed feed refresh issue (#87)
Aditya13s Jul 4, 2023
d1c5b5d
UI revamp (#88)
sidsharma2002 Jul 11, 2023
f6b432a
image support in doubts and static thumbnail in user-profile
Jul 13, 2023
7b884c3
version change
Jul 13, 2023
7359167
wip added ui for poll func
KrishnaTech6 Jun 25, 2023
72bbc3c
update: ui for poll create and view
KrishnaTech6 Jun 27, 2023
024151e
added create poll button in ViewDoubtsFragment
KrishnaTech6 Jun 27, 2023
aee9b5d
view poll vieholder added , changes in ui
KrishnaTech6 Jun 28, 2023
e9d058b
added poll view in main feed with multiple options, poll func WIP
KrishnaTech6 Jun 29, 2023
a29b47c
changes
KrishnaTech6 Jul 16, 2023
f3799f6
changes
KrishnaTech6 Jul 17, 2023
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
2 changes: 1 addition & 1 deletion .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
id 'kotlin-parcelize'
id 'kotlin-kapt'
}

android {
Expand All @@ -14,8 +15,8 @@ android {
applicationId "com.doubtless.doubtless"
minSdk 28
targetSdk 33
versionCode 6
versionName "0.1.3"
versionCode 10
versionName "0.1.7-poll"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
signingConfig signingConfigs.debug
Expand Down Expand Up @@ -72,6 +73,17 @@ dependencies {
implementation 'com.amplitude:analytics-android:1.+' // works with .+ and not 1.0 :/
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

def room_version = "2.5.2"

implementation("androidx.room:room-runtime:$room_version")
annotationProcessor("androidx.room:room-compiler:$room_version")

// To use Kotlin annotation processing tool (kapt)
kapt("androidx.room:room-compiler:$room_version")

// optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:$room_version")


// server
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ class AnalyticsTracker constructor(
private val userManager: UserManager
) {

fun trackTagsFragment(tag: String) {
val map = hashMapOf<String, String>()
map.putAll(getCommonAttrs())

map["tag"] = tag

amplitude.track("tag_feed_viewed", map)
}


fun trackLoginStarted() {
val map = hashMapOf<String, String>()
map.putAll(getCommonAttrs())
Expand Down Expand Up @@ -58,7 +68,7 @@ class AnalyticsTracker constructor(

fun trackDoubtUpVoted(doubtData: DoubtData) {
val map = getCommonAttrs().toMutableMap().apply {
this["doubt_data"] = doubtData.toString()
this["doubt_data"] = doubtData.toString()
}

amplitude.track("doubt_upvote", map)
Expand Down Expand Up @@ -86,7 +96,9 @@ class AnalyticsTracker constructor(
map["app_version_code"] = BuildConfig.VERSION_CODE.toString()

val user = userManager.getCachedUserData() ?: return map

map["user_id"] = user.id.toString()
map["user_email"] = user.email.toString()

if (user.local_user_attr?.tags != null)
map["user_tags"] = user.local_user_attr.tags.toString()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.doubtless.doubtless.constants

import com.doubtless.doubtless.BuildConfig

class FirestoreCollection {

companion object {
Expand All @@ -20,6 +18,11 @@ class FirestoreCollection {
val UPVOTE_DATA_USERS = "upvoted_users"
val DOWNVOTE_DATA_USERS = "downvoted_users"

val NOTIFICATION = "notifications"

const val TAG_MY_COLLEGE = "My College"
const val TAG_ALL = "All"


}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.doubtless.doubtless.constants

object GamificationConstants {
val MENTOR_XP_THRESHOLD = 1000
}
113 changes: 101 additions & 12 deletions app/src/main/java/com/doubtless/doubtless/di/AppCompositionRoot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.amplitude.android.Configuration
import com.doubtless.doubtless.DoubtlessApp
import com.doubtless.doubtless.R
import com.doubtless.doubtless.analytics.AnalyticsTracker
import com.doubtless.doubtless.localDatabase.AppDatabase
import com.doubtless.doubtless.navigation.FragNavigator
import com.doubtless.doubtless.navigation.Router
import com.doubtless.doubtless.network.DoubtlessServer
Expand All @@ -23,13 +24,15 @@ import com.doubtless.doubtless.screens.dashboard.usecases.DeleteAccountUseCase
import com.doubtless.doubtless.screens.dashboard.usecases.FetchUserDataUseCase
import com.doubtless.doubtless.screens.dashboard.usecases.FetchUserFeedByDateUseCase
import com.doubtless.doubtless.screens.doubt.DoubtData
import com.doubtless.doubtless.screens.doubt.usecases.DoubtDataSharedPrefUseCase
import com.doubtless.doubtless.screens.doubt.usecases.PostDoubtUseCase
import com.doubtless.doubtless.screens.doubt.usecases.VotingUseCase
import com.doubtless.doubtless.screens.doubt.usecases.*
import com.doubtless.doubtless.screens.home.entities.FeedConfig
import com.doubtless.doubtless.screens.home.usecases.FetchFeedByDateUseCase
import com.doubtless.doubtless.screens.home.usecases.FetchFeedByPopularityUseCase
import com.doubtless.doubtless.screens.home.usecases.FetchHomeFeedUseCase
import com.doubtless.doubtless.screens.inAppNotification.dao.InAppNotificationDao
import com.doubtless.doubtless.screens.inAppNotification.usecases.FetchInAppNotificationUseCase
import com.doubtless.doubtless.screens.inAppNotification.usecases.FetchUnreadNotificationUseCase
import com.doubtless.doubtless.screens.inAppNotification.usecases.MarkInAppNotificationsReadUseCase
import com.doubtless.doubtless.screens.main.MainActivity
import com.doubtless.doubtless.screens.main.MainFragment
import com.doubtless.doubtless.screens.onboarding.usecases.AddOnBoardingDataUseCase
Expand Down Expand Up @@ -84,11 +87,15 @@ class AppCompositionRoot(appContext: DoubtlessApp) {
}

private fun getFetchFeedByPopularityUseCase(): FetchFeedByPopularityUseCase {
return FetchFeedByPopularityUseCase(FirebaseFirestore.getInstance())
return FetchFeedByPopularityUseCase(getMentorsWhoInteractedUseCase(), FirebaseFirestore.getInstance())
}

private fun getFetchFeedByDataUseCase(): FetchFeedByDateUseCase {
return FetchFeedByDateUseCase(FirebaseFirestore.getInstance())
return FetchFeedByDateUseCase(getMentorsWhoInteractedUseCase(), FirebaseFirestore.getInstance())
}

private fun getMentorsWhoInteractedUseCase(): FetchInteractedMentorDataForDoubt {
return FetchInteractedMentorDataForDoubt(FirebaseFirestore.getInstance())
}

// --------- Answer Screen ------------
Expand Down Expand Up @@ -132,14 +139,54 @@ class AppCompositionRoot(appContext: DoubtlessApp) {
return PostDoubtUseCase(getServer())
}

// ------- Common --------
// --------- InApp Notification ----------

fun getFetchNotificationUseCase(): FetchInAppNotificationUseCase {
return FetchInAppNotificationUseCase(
getInAppNotificationDao(),
getFetchUnreadNotificationUseCase()
)
}

fun getMarkInAppNotificationsReadUseCase(): MarkInAppNotificationsReadUseCase {
return MarkInAppNotificationsReadUseCase(
getInAppNotificationDao(),
FirebaseFirestore.getInstance()
)
}

private fun getFetchUnreadNotificationUseCase(): FetchUnreadNotificationUseCase {
return FetchUnreadNotificationUseCase(FirebaseFirestore.getInstance(), getUserManager())
}

private fun getInAppNotificationDao(): InAppNotificationDao {
return AppDatabase.getDbInstance().inAppNotificationDao()
}

// ------- Doubt Preview --------

fun getAnswerVotingDoubtCase(answerData: AnswerData): VotingUseCase {
return VotingUseCase(FirebaseFirestore.getInstance(), getUserManager().getCachedUserData()!!, true, answerData, null)
return VotingUseCase(
FirebaseFirestore.getInstance(),
getUserManager().getCachedUserData()!!,
true,
answerData,
null
)
}

fun getDoubtVotingDoubtCase(doubtData: DoubtData): VotingUseCase {
return VotingUseCase(FirebaseFirestore.getInstance(), getUserManager().getCachedUserData()!!, false, null, doubtData)
return VotingUseCase(
FirebaseFirestore.getInstance(),
getUserManager().getCachedUserData()!!,
false,
null,
doubtData
)
}

fun getFetchDoubtDataFromDoubtIdUseCase(): FetchDoubtDataFromDoubtIdUseCase {
return FetchDoubtDataFromDoubtIdUseCase(FirebaseFirestore.getInstance())
}

// ------- User ---------
Expand Down Expand Up @@ -200,21 +247,54 @@ class AppCompositionRoot(appContext: DoubtlessApp) {
return null
}

fun getCreateFragmentNavigator(mainActivity: MainActivity): FragNavigator? {
val createFrag =
(mainActivity.supportFragmentManager.findFragmentByTag("MainFragment") as MainFragment?)
?.childFragmentManager?.findFragmentByTag("mainfrag_1")

if (createFrag != null) {
return DoubtlessApp.getInstance().getAppCompRoot()
.getFragNavigator(createFrag.childFragmentManager, R.id.bottomNav_child_container)
}

return null
}

fun getInAppFragNavigator(mainActivity: MainActivity): FragNavigator? {

val inAppFrag =
(mainActivity.supportFragmentManager.findFragmentByTag("MainFragment") as MainFragment?)
?.childFragmentManager?.findFragmentByTag("mainfrag_2")

if (inAppFrag != null) {
return DoubtlessApp.getInstance().getAppCompRoot()
.getFragNavigator(inAppFrag.childFragmentManager, R.id.bottomNav_child_container)
}

return null
}

fun getDashboardFragNavigator(mainActivity: MainActivity): FragNavigator? {

val dashboardFrag =
(mainActivity.supportFragmentManager.findFragmentByTag("MainFragment") as MainFragment?)
?.childFragmentManager?.findFragmentByTag("mainfrag_2")
?.childFragmentManager?.findFragmentByTag("mainfrag_3")

if (dashboardFrag != null) {
return DoubtlessApp.getInstance().getAppCompRoot()
.getFragNavigator(dashboardFrag.childFragmentManager, R.id.bottomNav_child_container)
.getFragNavigator(
dashboardFrag.childFragmentManager,
R.id.bottomNav_child_container
)
}

return null
}

private fun getFragNavigator(supportFragmentManager: FragmentManager, @IdRes containerId: Int ): FragNavigator {
private fun getFragNavigator(
supportFragmentManager: FragmentManager,
@IdRes containerId: Int
): FragNavigator {
return FragNavigator(
containerId,
supportFragmentManager
Expand Down Expand Up @@ -272,16 +352,25 @@ class AppCompositionRoot(appContext: DoubtlessApp) {
return remoteConfig
}

// --------- Dashboard -----------
fun getFetchUserDataUseCase(): FetchUserDataUseCase {
return FetchUserDataUseCase(
FetchUserFeedByDateUseCase(FirebaseFirestore.getInstance()),
FirebaseFirestore.getInstance()
)
}

fun getDeleteAccountUseCase() : DeleteAccountUseCase {
fun getDeleteAccountUseCase(): DeleteAccountUseCase {
return DeleteAccountUseCase(
FirebaseFirestore.getInstance()
)
}

// --------- Home Main Screen -----------

fun getFetchFilterTagsUseCase(): FetchFilterTagsUseCase {
return FetchFilterTagsUseCase(
FirebaseFirestore.getInstance()
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.doubtless.doubtless.localDatabase

import androidx.room.*
import com.doubtless.doubtless.DoubtlessApp
import com.doubtless.doubtless.screens.inAppNotification.dao.InAppNotificationDao
import com.doubtless.doubtless.screens.inAppNotification.model.InAppNotificationEntity

class AppDatabase {
@Database(entities = [InAppNotificationEntity::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppDB : RoomDatabase() {
abstract fun inAppNotificationDao(): InAppNotificationDao
}

companion object {

private var database: AppDB? = null

@Synchronized
fun getDbInstance(): AppDB {

if (database == null) {
database = Room.databaseBuilder(
context = DoubtlessApp.getInstance(),
klass = AppDB::class.java,
name = "doubtless-db"
).build()
}

return database!!
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.doubtless.doubtless.localDatabase

import androidx.room.TypeConverter
import com.google.firebase.Timestamp
import com.google.gson.Gson
import java.util.*

class Converters {

private val gson = Gson()

@TypeConverter
fun longToTimestamp(value: Long): Timestamp {
return Timestamp(Date(value))
}

@TypeConverter
fun timestampToLong(timestamp: Timestamp): Long {
return timestamp.toDate().time
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.fragment.app.FragmentManager
import com.doubtless.doubtless.R
import com.doubtless.doubtless.screens.answers.AnswersFragment
import com.doubtless.doubtless.screens.doubt.DoubtData
import com.doubtless.doubtless.screens.poll.CreatePollFragment
import com.doubtless.doubtless.screens.search.SearchFragment

class FragNavigator constructor(
Expand Down Expand Up @@ -44,4 +45,17 @@ class FragNavigator constructor(
.commitAllowingStateLoss()
}

fun moveToCreatePollFragment(){
supportFragmentManager.beginTransaction()
.setCustomAnimations(
/* enter = */ R.anim.slide_in_right,
/* exit = */ R.anim.slide_out_left,
/* popEnter = */ R.anim.slide_in_left,
/* popExit = */ R.anim.slide_out_right)
.replace(containerId, CreatePollFragment())
.addToBackStack(null)
.setReorderingAllowed(true)
.commitAllowingStateLoss()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.Intent
import com.doubtless.doubtless.screens.onboarding.OnBoardingActivity
import com.doubtless.doubtless.screens.auth.LoginActivity
import com.doubtless.doubtless.screens.main.MainActivity
import com.doubtless.doubtless.screens.poll.CreatePollFragment

class Router {

Expand All @@ -22,5 +23,4 @@ class Router {
val i = Intent(activity, OnBoardingActivity::class.java)
activity.startActivity(i)
}

}
Loading