Skip to content

Commit e858cc5

Browse files
Merge branch 'master' into MBL-19970-fix-breaking-e2e-tests
2 parents d144366 + 1303261 commit e858cc5

208 files changed

Lines changed: 7319 additions & 66 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (C) 2026 - present Instructure, Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, version 3 of the License.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
package com.instructure.parentapp.di.feature
17+
18+
import com.instructure.canvasapi2.apis.UserAPI
19+
import com.instructure.canvasapi2.utils.ApiPrefs
20+
import com.instructure.canvasapi2.utils.ConsentPrefs
21+
import com.instructure.pandautils.features.cookieconsent.AnalyticsConsentHandler
22+
import com.instructure.pandautils.features.cookieconsent.CookieConsentNamespace
23+
import com.instructure.pandautils.utils.FeatureFlagProvider
24+
import dagger.Module
25+
import dagger.Provides
26+
import dagger.hilt.InstallIn
27+
import dagger.hilt.components.SingletonComponent
28+
29+
@Module
30+
@InstallIn(SingletonComponent::class)
31+
class CookieConsentModule {
32+
33+
@Provides
34+
fun provideCookieConsentNamespace(): CookieConsentNamespace {
35+
return CookieConsentNamespace.PARENT
36+
}
37+
38+
@Provides
39+
fun provideAnalyticsConsentHandler(
40+
userApi: UserAPI.UsersInterface,
41+
featureFlagProvider: FeatureFlagProvider,
42+
consentPrefs: ConsentPrefs,
43+
apiPrefs: ApiPrefs
44+
): AnalyticsConsentHandler {
45+
return object : AnalyticsConsentHandler(userApi, featureFlagProvider, consentPrefs, apiPrefs) {}
46+
}
47+
}

apps/parent/src/main/java/com/instructure/parentapp/di/feature/LoginModule.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ import com.instructure.canvasapi2.utils.Analytics
2626
import com.instructure.canvasapi2.utils.ApiPrefs
2727
import com.instructure.loginapi.login.LoginNavigation
2828
import com.instructure.loginapi.login.features.acceptableusepolicy.AcceptableUsePolicyRouter
29+
import com.instructure.loginapi.login.features.cookieconsent.CookieConsentRouter
2930
import com.instructure.loginapi.login.util.LoginPrefs
3031
import com.instructure.pandautils.features.reminder.AlarmScheduler
3132
import com.instructure.parentapp.features.login.ParentAcceptableUsePolicyRouter
33+
import com.instructure.parentapp.features.login.ParentCookieConsentRouter
3234
import com.instructure.parentapp.features.login.ParentLoginNavigation
3335
import com.instructure.parentapp.features.login.SignInActivity
3436
import dagger.Module
@@ -59,6 +61,11 @@ class LoginModule {
5961
): LoginNavigation {
6062
return ParentLoginNavigation(activity, alarmScheduler)
6163
}
64+
65+
@Provides
66+
fun provideCookieConsentRouter(activity: FragmentActivity): CookieConsentRouter {
67+
return ParentCookieConsentRouter(activity)
68+
}
6269
}
6370

6471
@Module

apps/parent/src/main/java/com/instructure/parentapp/features/login/ParentAcceptableUsePolicyRouter.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import androidx.fragment.app.FragmentActivity
2222
import com.instructure.canvasapi2.utils.Analytics
2323
import com.instructure.canvasapi2.utils.AnalyticsEventConstants
2424
import com.instructure.loginapi.login.features.acceptableusepolicy.AcceptableUsePolicyRouter
25+
import com.instructure.loginapi.login.features.cookieconsent.CookieConsentActivity
2526
import com.instructure.loginapi.login.tasks.LogoutTask
2627
import com.instructure.pandautils.features.reminder.AlarmScheduler
2728
import com.instructure.parentapp.R
28-
import com.instructure.parentapp.features.main.MainActivity
2929
import com.instructure.parentapp.features.webview.HtmlContentActivity
3030
import com.instructure.parentapp.util.ParentLogoutTask
3131

@@ -42,8 +42,9 @@ class ParentAcceptableUsePolicyRouter(
4242
override fun startApp() {
4343
CookieManager.getInstance().flush()
4444

45-
val intent = Intent(activity, MainActivity::class.java)
45+
val intent = Intent(activity, CookieConsentActivity::class.java)
4646
activity.intent?.extras?.let { intent.putExtras(it) }
47+
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
4748
activity.startActivity(intent)
4849
}
4950

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (C) 2026 - present Instructure, Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, version 3 of the License.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
package com.instructure.parentapp.features.login
17+
18+
import android.content.Intent
19+
import androidx.fragment.app.FragmentActivity
20+
import com.instructure.loginapi.login.features.cookieconsent.CookieConsentRouter
21+
import com.instructure.parentapp.features.main.MainActivity
22+
23+
class ParentCookieConsentRouter(
24+
private val activity: FragmentActivity
25+
) : CookieConsentRouter {
26+
27+
override fun startApp() {
28+
val intent = Intent(activity, MainActivity::class.java)
29+
activity.intent?.extras?.let { intent.putExtras(it) }
30+
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
31+
activity.startActivity(intent)
32+
}
33+
}

apps/parent/src/main/java/com/instructure/parentapp/features/login/routevalidator/RouteValidatorAction.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ sealed class RouteValidatorAction {
2929
data class ShowToast(val message: String) : RouteValidatorAction()
3030
data class StartSignInActivity(val accountDomain: AccountDomain) : RouteValidatorAction()
3131
data object StartLoginActivity : RouteValidatorAction()
32+
data object StartCookieConsent : RouteValidatorAction()
3233
}

apps/parent/src/main/java/com/instructure/parentapp/features/login/routevalidator/RouteValidatorActivity.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import com.instructure.pandautils.binding.viewBinding
3030
import com.instructure.pandautils.utils.Const
3131
import com.instructure.pandautils.utils.collectOneOffEvents
3232
import com.instructure.parentapp.databinding.ActivityRouteValidatorBinding
33+
import com.instructure.loginapi.login.features.cookieconsent.CookieConsentActivity
3334
import com.instructure.parentapp.features.login.LoginActivity
3435
import com.instructure.parentapp.features.login.SignInActivity
3536
import com.instructure.parentapp.features.main.MainActivity
@@ -60,6 +61,7 @@ class RouteValidatorActivity : BaseCanvasActivity() {
6061
is RouteValidatorAction.ShowToast -> Toast.makeText(this, action.message, Toast.LENGTH_LONG).show()
6162
is RouteValidatorAction.StartSignInActivity -> startSignInActivity(action.accountDomain)
6263
is RouteValidatorAction.StartLoginActivity -> startLoginActivity()
64+
is RouteValidatorAction.StartCookieConsent -> startCookieConsent()
6365
}
6466
}
6567

@@ -92,6 +94,13 @@ class RouteValidatorActivity : BaseCanvasActivity() {
9294
finish()
9395
}
9496

97+
private fun startCookieConsent() {
98+
val intent = Intent(this, CookieConsentActivity::class.java)
99+
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
100+
startActivity(intent)
101+
finish()
102+
}
103+
95104
companion object {
96105
fun createIntent(context: Context, uri: Uri): Intent {
97106
val intent = Intent(context, RouteValidatorActivity::class.java)

apps/parent/src/main/java/com/instructure/parentapp/features/login/routevalidator/RouteValidatorViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class RouteValidatorViewModel @Inject constructor(
108108
} else {
109109
// Log the analytics - only for real logins, not masquerading
110110
logQREvent(apiPrefs.domain, true)
111-
postActionWithDelay(RouteValidatorAction.StartMainActivity())
111+
postActionWithDelay(RouteValidatorAction.StartCookieConsent)
112112
}
113113
return@tryLaunch
114114
} catch (e: Throwable) {

apps/parent/src/main/java/com/instructure/parentapp/features/settings/ParentSettingsBehaviour.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ParentSettingsBehaviour(private val selectedStudentHolder: SelectedStudent
2626
get() = mapOf(
2727
R.string.preferences to listOf(SettingsItem.APP_THEME),
2828
R.string.inboxSettingsTitle to listOf(SettingsItem.INBOX_SIGNATURE),
29-
R.string.legal to listOf(SettingsItem.ABOUT, SettingsItem.LEGAL)
29+
R.string.legal to listOf(SettingsItem.ABOUT, SettingsItem.LEGAL, SettingsItem.PRIVACY)
3030
)
3131

3232
override suspend fun applyAppSpecificColorSettings() {

apps/parent/src/main/java/com/instructure/parentapp/features/settings/ParentSettingsRouter.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,8 @@ class ParentSettingsRouter(private val navigation: Navigation, private val activ
2424
override fun navigateToInboxSignature() {
2525
navigation.navigate(activity, navigation.inboxSignatureSettings)
2626
}
27+
28+
override fun navigateToPrivacySettings() {
29+
navigation.navigate(activity, navigation.privacySettings)
30+
}
2731
}

apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashViewModel.kt

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import androidx.lifecycle.ViewModel
2323
import androidx.lifecycle.viewModelScope
2424
import com.instructure.canvasapi2.models.User
2525
import com.instructure.canvasapi2.utils.ApiPrefs
26+
import com.instructure.canvasapi2.utils.ConsentPrefs
2627
import com.instructure.canvasapi2.utils.weave.catch
2728
import com.instructure.canvasapi2.utils.weave.tryLaunch
2829
import com.instructure.pandautils.utils.ColorKeeper
@@ -43,6 +44,7 @@ class SplashViewModel @Inject constructor(
4344
@ApplicationContext private val context: Context,
4445
private val repository: SplashRepository,
4546
private val apiPrefs: ApiPrefs,
47+
private val consentPrefs: ConsentPrefs,
4648
private val colorKeeper: ColorKeeper,
4749
private val featureFlagProvider: FeatureFlagProvider,
4850
savedStateHandle: SavedStateHandle
@@ -83,18 +85,20 @@ class SplashViewModel @Inject constructor(
8385
}
8486
}
8587

86-
val sendUsageMetrics = repository.getSendUsageMetrics()
87-
if (sendUsageMetrics) {
88-
val userWithIds = repository.getSelfWithUuid()
89-
val visitorData = mapOf(
90-
"locale" to apiPrefs.effectiveLocale,
91-
)
92-
val accountData = mapOf(
93-
"surveyOptOut" to featureFlagProvider.checkAccountSurveyNotificationsFlag()
94-
)
95-
Pendo.startSession(userWithIds?.uuid?.SHA256().orEmpty(), userWithIds?.accountUuid.orEmpty(), visitorData, accountData)
96-
} else {
97-
Pendo.endSession()
88+
if (consentPrefs.currentUserConsent == true) {
89+
val sendUsageMetrics = repository.getSendUsageMetrics()
90+
if (sendUsageMetrics) {
91+
val userWithIds = repository.getSelfWithUuid()
92+
val visitorData = mapOf(
93+
"locale" to apiPrefs.effectiveLocale,
94+
)
95+
val accountData = mapOf(
96+
"surveyOptOut" to featureFlagProvider.checkAccountSurveyNotificationsFlag()
97+
)
98+
Pendo.startSession(userWithIds?.uuid?.SHA256().orEmpty(), userWithIds?.accountUuid.orEmpty(), visitorData, accountData)
99+
} else {
100+
Pendo.endSession()
101+
}
98102
}
99103

100104
val students = repository.getStudents()

0 commit comments

Comments
 (0)