Skip to content
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

feat: [FC-0047] Calendar synchronization #330

Merged
merged 37 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4ff1d21
feat: Created calendar setting screen
PavloNetrebchuk Apr 30, 2024
7649338
Merge remote-tracking branch 'origin/develop' into feat/calendar
PavloNetrebchuk May 15, 2024
6e09d35
feat: CalendarAccessDialog
PavloNetrebchuk May 16, 2024
ddd9c64
feat: NewCalendarDialog
PavloNetrebchuk May 17, 2024
437febc
fix: Fixes according to PR feedback
PavloNetrebchuk May 24, 2024
90d3f6b
feat: Create calendar
PavloNetrebchuk May 27, 2024
f80afcc
fix: Fixes according to PR feedback
PavloNetrebchuk May 24, 2024
54ab763
Merge remote-tracking branch 'origin/feat/calendar' into feat/calenda…
PavloNetrebchuk May 28, 2024
267b9b4
feat: Creating calendar
PavloNetrebchuk May 28, 2024
e2e2b8d
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk May 31, 2024
2f8c9f5
feat: Creating a calendar, tryToSyncCalendar logic, CalendarUIState, …
PavloNetrebchuk May 31, 2024
2093d79
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk May 31, 2024
6a4783d
feat: CalendarSettingsView
PavloNetrebchuk Jun 3, 2024
afbab8e
feat: Removed calendar logic from course home, edit calendar dialog
PavloNetrebchuk Jun 3, 2024
9804542
feat: Add events to calendar
PavloNetrebchuk Jun 3, 2024
c774d3b
fix: Save CourseCalendarEventEntity to DB
PavloNetrebchuk Jun 4, 2024
3a4b34e
feat: CoursesToSyncFragment UI
PavloNetrebchuk Jun 4, 2024
b44b9a6
feat: All Calendar sync logic
PavloNetrebchuk Jun 5, 2024
02b0a63
feat: DisableCalendarSyncDialogFragment
PavloNetrebchuk Jun 5, 2024
f371e98
refactor: Calendar repository refactoring, minor UI fixes
PavloNetrebchuk Jun 5, 2024
fe06870
refactor: Calendar Manager refactor
PavloNetrebchuk Jun 5, 2024
0fec040
fix: Fixes according to code review feedback
PavloNetrebchuk Jun 6, 2024
8abd36b
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk Jun 6, 2024
8c684e3
feat: Save calendar on logout, remove on different user login
PavloNetrebchuk Jun 7, 2024
2b25e47
feat: Notification for CalendarSyncWorker, junit test fix
PavloNetrebchuk Jun 7, 2024
87c23c9
feat: removeUnenrolledCourseEvents
PavloNetrebchuk Jun 8, 2024
f3f704d
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk Jun 10, 2024
7010639
feat: Calendar sync state on CourseDatesScreen
PavloNetrebchuk Jun 10, 2024
f55f2cd
fix: Crash CoursesToSyncFragment in offline mode
PavloNetrebchuk Jun 11, 2024
6508b20
fix: Fixes according to QA feedback
PavloNetrebchuk Jun 12, 2024
7b7c58e
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk Jun 13, 2024
631ef1a
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk Jun 20, 2024
6761fb7
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk Jun 26, 2024
9f7f459
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk Jul 9, 2024
0b2c381
Merge remote-tracking branch 'origin/develop' into feat/calendar_sync
PavloNetrebchuk Jul 9, 2024
71ab360
fix: Calendar Permission crash
PavloNetrebchuk Jul 12, 2024
5cd96fb
fix: Fixes according to PR feedback
PavloNetrebchuk Jul 17, 2024
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
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

</application>

</manifest>
4 changes: 4 additions & 0 deletions app/src/main/java/org/openedx/app/AppActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.openedx.core.presentation.global.WindowSizeHolder
import org.openedx.core.ui.WindowSize
import org.openedx.core.ui.WindowType
import org.openedx.core.utils.Logger
import org.openedx.core.worker.CalendarSyncScheduler
import org.openedx.profile.presentation.ProfileRouter
import org.openedx.whatsnew.WhatsNewManager
import org.openedx.whatsnew.presentation.whatsnew.WhatsNewFragment
Expand All @@ -50,6 +51,7 @@ class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder {
private val whatsNewManager by inject<WhatsNewManager>()
private val corePreferencesManager by inject<CorePreferences>()
private val profileRouter by inject<ProfileRouter>()
private val calendarSyncScheduler by inject<CalendarSyncScheduler>()

private val branchLogger = Logger(BRANCH_TAG)

Expand Down Expand Up @@ -160,6 +162,8 @@ class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder {
viewModel.logoutUser.observe(this) {
profileRouter.restartApp(supportFragmentManager, viewModel.isLogistrationEnabled)
}

calendarSyncScheduler.scheduleDailySync()
}

override fun onStart() {
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/java/org/openedx/app/AppRouter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.openedx.auth.presentation.logistration.LogistrationFragment
import org.openedx.auth.presentation.restore.RestorePasswordFragment
import org.openedx.auth.presentation.signin.SignInFragment
import org.openedx.auth.presentation.signup.SignUpFragment
import org.openedx.core.CalendarRouter
import org.openedx.core.FragmentViewType
import org.openedx.core.presentation.course.CourseViewMode
import org.openedx.core.presentation.global.app_upgrade.AppUpgradeRouter
Expand Down Expand Up @@ -46,6 +47,7 @@ import org.openedx.profile.domain.model.Account
import org.openedx.profile.presentation.ProfileRouter
import org.openedx.profile.presentation.anothersaccount.AnothersProfileFragment
import org.openedx.profile.presentation.calendar.CalendarFragment
import org.openedx.profile.presentation.calendar.CoursesToSyncFragment
import org.openedx.profile.presentation.delete.DeleteProfileFragment
import org.openedx.profile.presentation.edit.EditProfileFragment
import org.openedx.profile.presentation.manageaccount.ManageAccountFragment
Expand All @@ -56,7 +58,7 @@ import org.openedx.whatsnew.WhatsNewRouter
import org.openedx.whatsnew.presentation.whatsnew.WhatsNewFragment

class AppRouter : AuthRouter, DiscoveryRouter, DashboardRouter, CourseRouter, DiscussionRouter,
ProfileRouter, AppUpgradeRouter, WhatsNewRouter {
ProfileRouter, AppUpgradeRouter, WhatsNewRouter, CalendarRouter {

//region AuthRouter
override fun navigateToMain(
Expand Down Expand Up @@ -411,6 +413,10 @@ class AppRouter : AuthRouter, DiscoveryRouter, DashboardRouter, CourseRouter, Di
override fun navigateToCalendarSettings(fm: FragmentManager) {
replaceFragmentWithBackStack(fm, CalendarFragment())
}

override fun navigateToCoursesToSync(fm: FragmentManager) {
replaceFragmentWithBackStack(fm, CoursesToSyncFragment())
}
//endregion

fun getVisibleFragment(fm: FragmentManager): Fragment? {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/openedx/app/AppViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class AppViewModel(
if (System.currentTimeMillis() - logoutHandledAt > 5000) {
if (event.isForced) {
logoutHandledAt = System.currentTimeMillis()
preferencesManager.clear()
preferencesManager.clearCorePreferences()
withContext(dispatcher) {
room.clearAllTables()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ import android.content.Context
import com.google.gson.Gson
import org.openedx.app.BuildConfig
import org.openedx.core.data.model.User
import org.openedx.core.data.storage.CalendarPreferences
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.data.storage.InAppReviewPreferences
import org.openedx.core.domain.model.AppConfig
import org.openedx.core.domain.model.VideoQuality
import org.openedx.core.domain.model.VideoSettings
import org.openedx.core.extension.replaceSpace
import org.openedx.core.system.CalendarManager
import org.openedx.course.data.storage.CoursePreferences
import org.openedx.profile.data.model.Account
import org.openedx.profile.data.storage.ProfilePreferences
import org.openedx.whatsnew.data.storage.WhatsNewPreferences

class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences,
WhatsNewPreferences, InAppReviewPreferences, CoursePreferences {
WhatsNewPreferences, InAppReviewPreferences, CoursePreferences, CalendarPreferences {

private val sharedPreferences =
context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE)
Expand All @@ -37,7 +39,7 @@ class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences
}.apply()
}

private fun getLong(key: String): Long = sharedPreferences.getLong(key, 0L)
private fun getLong(key: String, defValue: Long = 0): Long = sharedPreferences.getLong(key, defValue)

private fun saveBoolean(key: String, value: Boolean) {
sharedPreferences.edit().apply {
Expand All @@ -49,7 +51,7 @@ class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences
return sharedPreferences.getBoolean(key, defValue)
}

override fun clear() {
override fun clearCorePreferences() {
sharedPreferences.edit().apply {
remove(ACCESS_TOKEN)
remove(REFRESH_TOKEN)
Expand All @@ -59,6 +61,14 @@ class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences
}.apply()
}

override fun clearCalendarPreferences() {
sharedPreferences.edit().apply {
remove(CALENDAR_ID)
remove(IS_CALENDAR_SYNC_ENABLED)
remove(HIDE_INACTIVE_COURSES)
}.apply()
}

override var accessToken: String
set(value) {
saveString(ACCESS_TOKEN, value)
Expand All @@ -83,6 +93,12 @@ class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences
}
get() = getLong(EXPIRES_IN)

override var calendarId: Long
set(value) {
saveLong(CALENDAR_ID, value)
}
get() = getLong(CALENDAR_ID, CalendarManager.CALENDAR_DOES_NOT_EXIST)

override var user: User?
set(value) {
val userJson = Gson().toJson(value)
Expand Down Expand Up @@ -165,6 +181,24 @@ class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences
}
get() = getBoolean(RESET_APP_DIRECTORY, true)

override var isCalendarSyncEnabled: Boolean
set(value) {
saveBoolean(IS_CALENDAR_SYNC_ENABLED, value)
}
get() = getBoolean(IS_CALENDAR_SYNC_ENABLED, true)

override var calendarUser: String
set(value) {
saveString(CALENDAR_USER, value)
}
get() = getString(CALENDAR_USER)

override var isHideInactiveCourses: Boolean
set(value) {
saveBoolean(HIDE_INACTIVE_COURSES, value)
}
get() = getBoolean(HIDE_INACTIVE_COURSES, true)

override fun setCalendarSyncEventsDialogShown(courseName: String) {
saveBoolean(courseName.replaceSpace("_"), true)
}
Expand All @@ -186,6 +220,10 @@ class PreferencesManager(context: Context) : CorePreferences, ProfilePreferences
private const val VIDEO_SETTINGS_STREAMING_QUALITY = "video_settings_streaming_quality"
private const val VIDEO_SETTINGS_DOWNLOAD_QUALITY = "video_settings_download_quality"
private const val APP_CONFIG = "app_config"
private const val CALENDAR_ID = "CALENDAR_ID"
private const val RESET_APP_DIRECTORY = "reset_app_directory"
private const val IS_CALENDAR_SYNC_ENABLED = "IS_CALENDAR_SYNC_ENABLED"
private const val HIDE_INACTIVE_COURSES = "HIDE_INACTIVE_COURSES"
private const val CALENDAR_USER = "CALENDAR_USER"
}
}
24 changes: 21 additions & 3 deletions app/src/main/java/org/openedx/app/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,25 @@ import org.koin.core.qualifier.named
import org.koin.dsl.module
import org.openedx.app.AnalyticsManager
import org.openedx.app.AppAnalytics
import org.openedx.app.deeplink.DeepLinkRouter
import org.openedx.app.AppRouter
import org.openedx.app.BuildConfig
import org.openedx.app.data.storage.PreferencesManager
import org.openedx.app.deeplink.DeepLinkRouter
import org.openedx.app.room.AppDatabase
import org.openedx.app.room.DATABASE_NAME
import org.openedx.app.room.DatabaseManager
import org.openedx.auth.presentation.AgreementProvider
import org.openedx.auth.presentation.AuthAnalytics
import org.openedx.auth.presentation.AuthRouter
import org.openedx.auth.presentation.sso.FacebookAuthHelper
import org.openedx.auth.presentation.sso.GoogleAuthHelper
import org.openedx.auth.presentation.sso.MicrosoftAuthHelper
import org.openedx.auth.presentation.sso.OAuthHelper
import org.openedx.core.CalendarRouter
import org.openedx.core.ImageProcessor
import org.openedx.core.config.Config
import org.openedx.core.data.model.CourseEnrollments
import org.openedx.core.data.storage.CalendarPreferences
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.data.storage.InAppReviewPreferences
import org.openedx.core.module.DownloadWorkerController
Expand All @@ -48,7 +51,9 @@ import org.openedx.core.system.notifier.DiscoveryNotifier
import org.openedx.core.system.notifier.DownloadNotifier
import org.openedx.core.system.notifier.VideoNotifier
import org.openedx.core.system.notifier.app.AppNotifier
import org.openedx.core.system.notifier.calendar.CalendarNotifier
import org.openedx.core.utils.FileUtil
import org.openedx.core.worker.CalendarSyncScheduler
import org.openedx.course.data.storage.CoursePreferences
import org.openedx.course.presentation.CourseAnalytics
import org.openedx.course.presentation.CourseRouter
Expand All @@ -62,11 +67,12 @@ import org.openedx.discussion.system.notifier.DiscussionNotifier
import org.openedx.profile.data.storage.ProfilePreferences
import org.openedx.profile.presentation.ProfileAnalytics
import org.openedx.profile.presentation.ProfileRouter
import org.openedx.profile.system.notifier.ProfileNotifier
import org.openedx.profile.system.notifier.profile.ProfileNotifier
import org.openedx.whatsnew.WhatsNewManager
import org.openedx.whatsnew.WhatsNewRouter
import org.openedx.whatsnew.data.storage.WhatsNewPreferences
import org.openedx.whatsnew.presentation.WhatsNewAnalytics
import org.openedx.core.DatabaseManager as IDatabaseManager

val appModule = module {

Expand All @@ -77,11 +83,14 @@ val appModule = module {
single<WhatsNewPreferences> { get<PreferencesManager>() }
single<InAppReviewPreferences> { get<PreferencesManager>() }
single<CoursePreferences> { get<PreferencesManager>() }
single<CalendarPreferences> { get<PreferencesManager>() }

single { ResourceManager(get()) }
single { AppCookieManager(get(), get()) }
single { ReviewManagerFactory.create(get()) }
single { CalendarManager(get(), get(), get()) }
single { CalendarManager(get(), get()) }
single { DatabaseManager(get(), get(), get(), get()) }
single<IDatabaseManager> { get<DatabaseManager>() }

single { ImageProcessor(get()) }

Expand All @@ -98,6 +107,7 @@ val appModule = module {
single { DownloadNotifier() }
single { VideoNotifier() }
single { DiscoveryNotifier() }
single { CalendarNotifier() }

single { AppRouter() }
single<AuthRouter> { get<AppRouter>() }
Expand All @@ -109,6 +119,7 @@ val appModule = module {
single<WhatsNewRouter> { get<AppRouter>() }
single<AppUpgradeRouter> { get<AppRouter>() }
single { DeepLinkRouter(get(), get(), get(), get(), get(), get()) }
single<CalendarRouter> { get<AppRouter>() }

single { NetworkConnection(get()) }

Expand Down Expand Up @@ -150,6 +161,11 @@ val appModule = module {
room.downloadDao()
}

single {
val room = get<AppDatabase>()
room.calendarDao()
}

single {
FileDownloader()
}
Expand Down Expand Up @@ -184,4 +200,6 @@ val appModule = module {
factory { OAuthHelper(get(), get(), get()) }

factory { FileUtil(get()) }

single { CalendarSyncScheduler(get()) }
}
28 changes: 21 additions & 7 deletions app/src/main/java/org/openedx/app/di/ScreenModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import org.openedx.auth.presentation.restore.RestorePasswordViewModel
import org.openedx.auth.presentation.signin.SignInViewModel
import org.openedx.auth.presentation.signup.SignUpViewModel
import org.openedx.core.Validator
import org.openedx.core.domain.interactor.CalendarInteractor
import org.openedx.core.presentation.dialog.selectorbottomsheet.SelectDialogViewModel
import org.openedx.core.presentation.settings.video.VideoQualityViewModel
import org.openedx.core.repository.CalendarRepository
import org.openedx.core.ui.WindowSize
import org.openedx.course.data.repository.CourseRepository
import org.openedx.course.domain.interactor.CourseInteractor
Expand Down Expand Up @@ -58,6 +60,9 @@ import org.openedx.profile.domain.interactor.ProfileInteractor
import org.openedx.profile.domain.model.Account
import org.openedx.profile.presentation.anothersaccount.AnothersProfileViewModel
import org.openedx.profile.presentation.calendar.CalendarViewModel
import org.openedx.profile.presentation.calendar.CoursesToSyncViewModel
import org.openedx.profile.presentation.calendar.DisableCalendarSyncDialogViewModel
import org.openedx.profile.presentation.calendar.NewCalendarDialogViewModel
import org.openedx.profile.presentation.delete.DeleteProfileViewModel
import org.openedx.profile.presentation.edit.EditProfileViewModel
import org.openedx.profile.presentation.manageaccount.ManageAccountViewModel
Expand Down Expand Up @@ -109,6 +114,8 @@ val screenModule = module {
get(),
get(),
get(),
get(),
get(),
courseId,
infoType,
)
Expand Down Expand Up @@ -190,14 +197,21 @@ val screenModule = module {
get(),
get(),
get(),
get()
get(),
get(),
)
}
viewModel { ManageAccountViewModel(get(), get(), get(), get(), get()) }
viewModel { CalendarViewModel(get()) }
viewModel { CalendarViewModel(get(), get(), get(), get(), get(), get(), get()) }
viewModel { CoursesToSyncViewModel(get(), get(), get(), get()) }
viewModel { NewCalendarDialogViewModel(get(), get(), get(), get(), get(), get()) }
viewModel { DisableCalendarSyncDialogViewModel(get(), get(), get(), get()) }
factory { CalendarRepository(get(), get(), get()) }
factory { CalendarInteractor(get()) }

single { CourseRepository(get(), get(), get(), get(), get()) }
factory { CourseInteractor(get()) }

viewModel { (pathId: String, infoType: String) ->
CourseInfoViewModel(
pathId,
Expand All @@ -221,7 +235,8 @@ val screenModule = module {
get(),
get(),
get(),
get()
get(),
get(),
)
}
viewModel { (courseId: String, courseTitle: String, enrollmentMode: String, resumeBlockId: String) ->
Expand All @@ -239,7 +254,6 @@ val screenModule = module {
get(),
get(),
get(),
get(),
get()
)
}
Expand Down Expand Up @@ -327,10 +341,9 @@ val screenModule = module {
get(),
)
}
viewModel { (courseId: String, courseTitle: String, enrollmentMode: String) ->
viewModel { (courseId: String, enrollmentMode: String) ->
CourseDatesViewModel(
courseId,
courseTitle,
enrollmentMode,
get(),
get(),
Expand All @@ -339,7 +352,8 @@ val screenModule = module {
get(),
get(),
get(),
get()
get(),
get(),
)
}
viewModel { (courseId: String, handoutsType: String) ->
Expand Down
Loading
Loading