Skip to content
This repository has been archived by the owner on May 6, 2024. It is now read-only.

Commit

Permalink
feat: added option to delete downloaded videos from AccountFragment (#…
Browse files Browse the repository at this point in the history
…1849)

- Allow user to delete downloaded videos from Accounts
- Added relevant analytics
- Show a progress dialog for 2 sec while deleting
- Reset whole app external directory folder

fix: LEARNER-9786
  • Loading branch information
omerhabib26 authored Mar 1, 2024
1 parent 459dee2 commit bd6299c
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 8 deletions.
23 changes: 23 additions & 0 deletions OpenEdXMobile/res/layout/fragment_account.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,29 @@

</LinearLayout>

<TextView
android:id="@+id/lbl_delete_downloaded_videos"
style="@style/profile_field_title"
android:layout_width="match_parent"
android:layout_marginStart="@dimen/edx_default_margin"
android:layout_marginTop="@dimen/edx_default_margin"
android:layout_marginEnd="@dimen/edx_default_margin"
android:text="@string/delete_downloaded_videos_title" />

<TextView
android:id="@+id/tv_delete_downloaded_videos"
style="@style/profile_field_description"
android:text="@string/delete_downloaded_videos_description" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_delete_videos"
style="@style/edX.Widget.ProfileActionBorderedButton"
android:layout_width="match_parent"
android:layout_height="@dimen/profile_view_button_height"
android:layout_marginTop="@dimen/edx_half_margin"
android:text="@string/label_delete_all_videos" />


<View
android:layout_width="match_parent"
android:layout_height="@dimen/edx_line"
Expand Down
14 changes: 14 additions & 0 deletions OpenEdXMobile/res/values/video_strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,18 @@
<item quantity="one">%d min</item>
<item quantity="other">%d mins</item>
</plurals>

<!-- Title of Delete all downloaded videos -->
<string name="delete_downloaded_videos_title">Delete all downloaded videos</string>
<!-- Description of Delete all downloaded videos -->
<string name="delete_downloaded_videos_description">Remove all downloaded videos from your device.</string>
<!-- Title of Delete downloaded video dialog -->
<string name="delete_downloaded_videos_dialog_description">Are you sure you want to delete all downloaded videos from your device? This action cannot be undone.</string>
<!-- Title of Delete all videos button -->
<string name="label_delete_all_videos">Delete all videos</string>
<!-- Title of Deleting downloaded video progress dialog -->
<string name="deleting_downloaded_videos_title">Deleting downloaded videos…</string>
<!-- Message of Deleted downloaded video success snackbar -->
<string name="deleted_downloaded_videos_success">Downloaded videos deleted successfully.</string>

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -902,10 +902,12 @@ interface Values {
String DO_NOT_SELL_DATA_CLICKED = "edx.bi.app.profile.do_not_sell_data.clicked";
String SUBMIT_FEEDBACK_CLICKED = "edx.bi.app.profile.submit_feedback.clicked";

// Video Download Quality
// Video Downloads & Quality
String PROFILE_VIDEO_DOWNLOAD_QUALITY_CLICKED = "edx.bi.app.profile.video_download_quality.clicked";
String COURSE_VIDEOS_VIDEO_DOWNLOAD_QUALITY_CLICKED = "edx.bi.app.course_videos.video_download_quality.clicked";
String VIDEO_DOWNLOAD_QUALITY_CHANGED = "edx.bi.app.video_download_quality.changed";
String DELETE_DOWNLOADED_VIDEOS_CLICKED = "edx.bi.app.delete_downloaded_videos.clicked";
String DELETE_DOWNLOADED_VIDEOS = "edx.bi.app.delete_downloaded_videos";
// Account Registration
String REGISTRATION_OPT_IN_TURNED_ON = "edx.bi.app.user.register.opt_in.on";
String REGISTRATION_OPT_IN_TURNED_OFF = "edx.bi.app.user.register.opt_in.off";
Expand Down Expand Up @@ -1124,10 +1126,12 @@ interface Events {
String DO_NOT_SELL_DATA_CLICKED = "Do Not Sell Data Clicked";
String SUBMIT_FEEDBACK_CLICKED = "Submit feedback clicked";

// Video Download Quality
// Video Downloads & Quality
String PROFILE_VIDEO_DOWNLOAD_QUALITY_CLICKED = "Profile: Video Download Quality Clicked";
String COURSE_VIDEOS_VIDEO_DOWNLOAD_QUALITY_CLICKED = "Course Videos: Video Download Quality Clicked";
String VIDEO_DOWNLOAD_QUALITY_CHANGED = "Video Download Quality Changed";
String DELETE_DOWNLOADED_VIDEOS_CLICKED = "Delete Downloaded Videos Clicked";
String DELETE_DOWNLOADED_VIDEOS = "Delete Downloaded Videos";
// Account Registration
String REGISTRATION_OPT_IN_TURNED_ON = "Registration: Opt-in Turned On";
String REGISTRATION_OPT_IN_TURNED_OFF = "Registration: Opt-in Turned Off";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,17 @@ Integer updateDownloadCompleteInfoByDmId(long dmId, VideoModel de,
DataCallback<Integer> callback);

/**
* Returns list of all videos from the database.
* Returns list of all videos from the database for a specific username.
*
* @return
*/
List<VideoModel> getAllVideos(String username, DataCallback<List<VideoModel>> DataCallback);

/**
* Returns list of all videos from the database.
*/
List<VideoModel> getAllVideos(DataCallback<List<VideoModel>> DataCallback);

/**
* Returns list of all videos from the database for a specific course.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,14 @@ public List<VideoModel> getAllVideos(String username,
return enqueue(op);
}

@Override
public List<VideoModel> getAllVideos(DataCallback<List<VideoModel>> callback) {
DbOperationGetVideos op = new DbOperationGetVideos(false, DbStructure.Table.DOWNLOADS, null,
null, null, null);
op.setCallback(callback);
return enqueue(op);
}

@Override
public List<VideoModel> getAllVideosByCourse(@NonNull String courseId,
@Nullable DataCallback<List<VideoModel>> callback) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.edx.mobile.module.storage;

public class DeleteAllDownloadedVideosEvent {
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,18 @@ public interface IStorage {

/**
* Removes all videos from the database as well as NativeDownloadManager.
* This method fetches all ongoing downloads from the DB; iterates through the list
* This method fetches all downloads from the DB; iterates through the list
* and then calls the {@link #removeDownload(VideoModel)} method for each video
*/
void removeAllDownloads();

/**
* Removes all videos from the database as well as NativeDownloadManager.
* This method fetches all ongoing downloads from the DB; iterates through the list
* and then calls the {@link #removeDownload(VideoModel)} method for each video
*/
void removeAllOnGoingDownloads();

/**
* This method fetches all unenrolledVideos from the DB.
* Iterates through the list and then calls the remove Download method for each video
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,23 @@ public int removeDownloads(List<VideoModel> modelList) {

@Override
public void removeAllDownloads() {
db.getAllVideos(new DataCallback<List<VideoModel>>() {
@Override
public void onResult(List<VideoModel> result) {
removeDownloadsFromApp(result, null);
FileUtil.resetAppDirectory(context);
EventBus.getDefault().post(new DeleteAllDownloadedVideosEvent());
}

@Override
public void onFail(Exception ex) {
logger.error(ex);
}
});
}

@Override
public void removeAllOnGoingDownloads() {
final String username = loginPrefs.getUsername();
final String sha1Username;
if (TextUtils.isEmpty(username)) {
Expand Down
12 changes: 12 additions & 0 deletions OpenEdXMobile/src/main/java/org/edx/mobile/util/FileUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,16 @@ public static Uri getFileUriFromMediaStoreUri(@NonNull Context context, @NonNull
}
return null;
}

/**
* Deletes all the files and directories in the app's external storage directory.
*
* @param context The current context.
*/
public static void resetAppDirectory(@NonNull Context context) {
final File externalAppDir = getExternalAppDir(context);
if (externalAppDir != null) {
deleteRecursive(externalAppDir);
}
}
}
54 changes: 51 additions & 3 deletions OpenEdXMobile/src/main/java/org/edx/mobile/view/AccountFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.URLUtil
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide
Expand Down Expand Up @@ -38,6 +40,8 @@ import org.edx.mobile.module.analytics.InAppPurchasesAnalytics
import org.edx.mobile.module.prefs.FeaturesPrefs
import org.edx.mobile.module.prefs.LoginPrefs
import org.edx.mobile.module.prefs.UserPrefs
import org.edx.mobile.module.storage.DeleteAllDownloadedVideosEvent
import org.edx.mobile.module.storage.IStorage
import org.edx.mobile.user.UserAPI.AccountDataUpdatedCallback
import org.edx.mobile.user.UserService
import org.edx.mobile.util.AgreementUrlType
Expand Down Expand Up @@ -94,6 +98,9 @@ class AccountFragment : BaseFragment() {
@Inject
lateinit var iapAnalytics: InAppPurchasesAnalytics

@Inject
lateinit var storage: IStorage

private val courseViewModel: CourseViewModel by viewModels()
private val iapViewModel: InAppPurchasesViewModel by viewModels()

Expand Down Expand Up @@ -130,6 +137,7 @@ class AccountFragment : BaseFragment() {
initPurchases()
handleIntentBundle(arguments)
initVideoQuality()
initDeleteDownloadedVideos()
updateWifiSwitch()
updateSDCardSwitch()
initHelpFields()
Expand Down Expand Up @@ -171,7 +179,7 @@ class AccountFragment : BaseFragment() {
binding.btnRestorePurchases.setOnClickListener {
iapAnalytics.reset()
iapAnalytics.trackIAPEvent(Analytics.Events.IAP_RESTORE_PURCHASE_CLICKED)
showLoader()
showLoader(R.string.title_checking_purchases)
lifecycleScope.launch {
courseViewModel.fetchEnrolledCourses(
type = CourseViewModel.CoursesRequestType.STALE,
Expand Down Expand Up @@ -266,9 +274,9 @@ class AccountFragment : BaseFragment() {
fullScreenLoader.show(childFragmentManager, FullscreenLoaderDialogFragment.TAG)
}

private fun showLoader() {
private fun showLoader(@StringRes titleResId: Int) {
loaderDialog = AlertDialogFragment.newInstance(
R.string.title_checking_purchases,
titleResId,
R.layout.alert_dialog_progress
)
loaderDialog?.isCancelable = false
Expand Down Expand Up @@ -301,6 +309,30 @@ class AccountFragment : BaseFragment() {
binding.tvVideoDownloadQuality.setText(videoQuality.titleResId)
}

private fun initDeleteDownloadedVideos() {
binding.btnDeleteVideos.setOnClickListener {
trackEvent(
Analytics.Events.DELETE_DOWNLOADED_VIDEOS_CLICKED,
Analytics.Values.DELETE_DOWNLOADED_VIDEOS_CLICKED
)
AlertDialogFragment.newInstance(
getString(R.string.delete_downloaded_videos_title),
getString(R.string.delete_downloaded_videos_dialog_description),
getString(R.string.label_delete),
{ _, _ ->
showLoader(R.string.deleting_downloaded_videos_title)
storage.removeAllDownloads()
trackEvent(
Analytics.Events.DELETE_DOWNLOADED_VIDEOS,
Analytics.Values.DELETE_DOWNLOADED_VIDEOS
)
},
getString(R.string.label_cancel),
null
).show(childFragmentManager, null)
}
}

private fun initHelpFields() {
if (URLUtil.isValidUrl(featuresPrefs.feedbackFormUrl)) {
binding.btnSubmitFeedback.setVisibility(true)
Expand Down Expand Up @@ -605,6 +637,22 @@ class AccountFragment : BaseFragment() {
environment.analyticsRegistry.trackEvent(eventName, biValue)
}

@Subscribe(sticky = true)
@Suppress("UNUSED_PARAMETER")
fun onEventMainThread(event: DeleteAllDownloadedVideosEvent) {
binding.root.postDelayed(
{
loaderDialog?.dismiss()
Toast.makeText(
requireContext(),
R.string.deleted_downloaded_videos_success,
Toast.LENGTH_LONG
).show()
}, 2000
)

}

companion object {
@JvmStatic
fun newInstance(bundle: Bundle): AccountFragment {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ public void forceLogout(Context context, AnalyticsRegistry analyticsRegistry, No
*/
public void performManualLogout(Context context, AnalyticsRegistry analyticsRegistry, NotificationDelegate delegate) {
// Remove all ongoing downloads first which requires username
storage.removeAllDownloads();
storage.removeAllOnGoingDownloads();
loginAPI.logOut();
forceLogout(context, analyticsRegistry, delegate);
SecurityUtil.clearUserData(context);
Expand Down

0 comments on commit bd6299c

Please sign in to comment.