diff --git a/.gitignore b/.gitignore index ddeb227f3..83d5f3b6e 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,5 @@ fastlane/.idea apps/captures libs/DocumentScanner/build/ +apps/buildSrc/src/main/java/candroid.keystore +open_source_data/student/google-services.json diff --git a/.gitmodules b/.gitmodules index 06b7c3fb6..d13a3c5f9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "apps/mobile-offline-downloader-android"] path = apps/mobile-offline-downloader-android url = https://github.com/2uinc/mobile-offline-downloader-android.git + branch = main diff --git a/apps/build.gradle b/apps/build.gradle index a0b3f6aaa..e74b6b143 100644 --- a/apps/build.gradle +++ b/apps/build.gradle @@ -45,13 +45,6 @@ allprojects { } mavenCentral() maven { url 'https://jitpack.io' } - maven { - credentials { - username pspdfMavenUser - password pspdfMavenPass - } - url 'https://customers.pspdfkit.com/maven/' - } maven { url "https://maven.google.com/" } } } diff --git a/apps/buildSrc/src/main/java/GlobalDependencies.kt b/apps/buildSrc/src/main/java/GlobalDependencies.kt index ad676509b..25aa35d53 100644 --- a/apps/buildSrc/src/main/java/GlobalDependencies.kt +++ b/apps/buildSrc/src/main/java/GlobalDependencies.kt @@ -24,7 +24,6 @@ object Versions { /* Others */ const val APOLLO = "4.1.1" - const val PSPDFKIT = "2024.8.0" const val PHOTO_VIEW = "2.3.0" const val MOBIUS = "1.2.1" const val HILT = "2.52" @@ -127,7 +126,6 @@ object Libs { const val COMPOSE_VIEW_MODEL = "androidx.lifecycle:lifecycle-viewmodel-compose:${Versions.LIFECYCLE}" /* Media and content handling */ - const val PSPDFKIT = "com.pspdfkit:pspdfkit:${Versions.PSPDFKIT}" const val EXOPLAYER = "com.google.android.exoplayer:exoplayer:2.18.5" // This is deprecated, we should migrate to https://developer.android.com/guide/topics/media/media3/getting-started/migration-guide const val MEDIA3 = "androidx.media3:media3-exoplayer:${Versions.MEDIA3}" const val MEDIA3_UI = "androidx.media3:media3-ui:${Versions.MEDIA3}" diff --git a/apps/buildSrc/src/main/java/OfflineDependencies.kt b/apps/buildSrc/src/main/java/OfflineDependencies.kt index f273c6922..781da524f 100644 --- a/apps/buildSrc/src/main/java/OfflineDependencies.kt +++ b/apps/buildSrc/src/main/java/OfflineDependencies.kt @@ -1,6 +1,6 @@ object OfflineDependencies { - const val versionCode = 10 - const val versionName = "1.5" + const val versionCode = 15 + const val versionName = "1.9" const val constraintLayout = "2.1.0" const val appCompat = "1.5.0" const val recyclerView = "1.2.1" diff --git a/apps/mobile-offline-downloader-android b/apps/mobile-offline-downloader-android index 0282231d7..b0882937c 160000 --- a/apps/mobile-offline-downloader-android +++ b/apps/mobile-offline-downloader-android @@ -1 +1 @@ -Subproject commit 0282231d77782a5738d3d87a12568402533bdb44 +Subproject commit b0882937c27056276c5933ceb53775c334432ea5 diff --git a/apps/parent/proguard-rules.txt b/apps/parent/proguard-rules.txt index bde42b751..7e5a37dfe 100644 --- a/apps/parent/proguard-rules.txt +++ b/apps/parent/proguard-rules.txt @@ -187,16 +187,6 @@ -dontwarn okhttp3.** -keep class okhttp3.** { *; } -# PSPDFKit --keep class com.pspdfkit.** { *; } --dontwarn com.pspdfkit.** --dontwarn sun.misc.** --dontwarn android.view.WindowInsets --dontwarn android.graphics.Insets --dontwarn edu.umd.cs.findbugs.annotations.SuppressWarnings --keepnames class io.reactivex.android.schedulers.AndroidSchedulers --keepnames class io.reactivex.Observable - # RxJava -keep class rx.internal.util.unsafe.** { *; } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/util/AppManager.kt b/apps/parent/src/main/java/com/instructure/parentapp/util/AppManager.kt index 0efb1d333..bbb9fb82a 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/util/AppManager.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/util/AppManager.kt @@ -59,6 +59,6 @@ class AppManager : BaseAppManager() { private fun initPendo() { val options = Pendo.PendoOptions.Builder().setJetpackComposeBeta(true).build() - Pendo.setup(this, BuildConfig.PENDO_TOKEN, options, null) +// Pendo.setup(this, BuildConfig.PENDO_TOKEN, options, null) } } \ No newline at end of file diff --git a/apps/settings.gradle b/apps/settings.gradle index 255c7d14b..b220898ad 100644 --- a/apps/settings.gradle +++ b/apps/settings.gradle @@ -1,7 +1,5 @@ /* Top-level project modules */ include ':student' -include ':teacher' -include ':parent' /* Library modules */ include ':annotations' diff --git a/apps/student/build.gradle b/apps/student/build.gradle index 185936cf5..1d0d6f50e 100644 --- a/apps/student/build.gradle +++ b/apps/student/build.gradle @@ -51,7 +51,6 @@ android { /* Add private data */ PrivateData.merge(project, "student") buildConfigField "String", "TRANSLATION_TAGS", "\"${LocaleScanner.getAvailableLanguageTags(project)}\"" - buildConfigField "String", "PSPDFKIT_LICENSE_KEY", "\"$pspdfkitLicenseKey\"" testBuildType = "debug" diff --git a/apps/student/proguard-rules.txt b/apps/student/proguard-rules.txt index 1b35a6619..02ff2a7a8 100644 --- a/apps/student/proguard-rules.txt +++ b/apps/student/proguard-rules.txt @@ -193,16 +193,6 @@ -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn okhttp3.** -#PSPDFKit --keep class com.pspdfkit.** { *; } --dontwarn sun.misc.** --dontwarn edu.umd.cs.findbugs.annotations.SuppressWarnings --keepnames class io.reactivex.android.schedulers.AndroidSchedulers --keepnames class io.reactivex.Observable --dontwarn com.pspdfkit.** --dontwarn android.view.WindowInsets --dontwarn android.graphics.Insets - # Keep third party lib class names. PSPDFKit relies on those class names to be present. -keepnames class rx.android.schedulers.AndroidSchedulers -keepnames class rx.Observable diff --git a/apps/student/src/androidTest/java/com/instructure/student/ui/interaction/PdfInteractionTest.kt b/apps/student/src/androidTest/java/com/instructure/student/ui/interaction/PdfInteractionTest.kt index 4c8d933d2..72d47e1de 100644 --- a/apps/student/src/androidTest/java/com/instructure/student/ui/interaction/PdfInteractionTest.kt +++ b/apps/student/src/androidTest/java/com/instructure/student/ui/interaction/PdfInteractionTest.kt @@ -127,55 +127,6 @@ class PdfInteractionTest : StudentComposeTest() { fileListPage.assertPdfPreviewDisplayed() } - @Test - @TestMetaData(Priority.IMPORTANT, FeatureCategory.ASSIGNMENTS, TestCategory.INTERACTION, SecondaryFeatureCategory.SUBMISSIONS_ANNOTATIONS) - fun testAnnotations_openPdfsInPSPDFKitFromLinksInAssignment() { - // Annotation toolbar icon needs to be present, this link is specific to assignment details, as that was the advertised use case - val data = MockCanvas.init( - studentCount = 1, - courseCount = 1 - ) - - val course = data.courses.values.first() - val student = data.students[0] - val token = data.tokenFor(student)!! - data.addAssignmentsToGroups(course) - tokenLogin(data.domain, token, student) - routeTo("courses/${course.id}/assignments", data.domain) - - val fileId = data.newItemId() - val url = """https://mock-data.instructure.com/courses/${course.id}/files/${fileId}/download?""" - - data.addFileToCourse( - courseId = course.id, - displayName = pdfFileName, - contentType = "application/pdf", - fileId = fileId, - url = url - ) - - val uniqueFileName = OpenMediaAsyncTaskLoader.makeFilenameUnique(pdfFileName, url, fileId.toString()) - - cacheFile(student.id.toString(), uniqueFileName) - - val pdfUrlElementId = "testLinkElement" - val assignmentDescriptionHtml = """pdf baby!!!""" - - val assignment = data.addAssignment(courseId = course.id, submissionTypeList = listOf(Assignment.SubmissionType.ONLINE_UPLOAD), description = assignmentDescriptionHtml) - - assignmentListPage.refreshAssignmentList() - assignmentListPage.clickAssignment(assignment) - assignmentDetailsPage.assertAssignmentDetails(assignment) - - // Scroll to the description, as it will likely be offscreen for landscape tests - assignmentDetailsPage.scrollToAssignmentDescription() - - // Click the url in the description to load the pdf - Web.onWebView(withId(R.id.contentWebView)) - .withElement(DriverAtoms.findElement(Locator.ID, pdfUrlElementId)) - .perform(DriverAtoms.webClick()) - fileListPage.assertPdfPreviewDisplayed() - } private fun getToCourse(): MockCanvas { val data = MockCanvas.init( diff --git a/apps/student/src/main/AndroidManifest.xml b/apps/student/src/main/AndroidManifest.xml index 0d0f633e3..a584e1694 100644 --- a/apps/student/src/main/AndroidManifest.xml +++ b/apps/student/src/main/AndroidManifest.xml @@ -155,11 +155,6 @@ android:foregroundServiceType="dataSync" android:exported="false" /> - - diff --git a/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentListFragment.kt b/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentListFragment.kt deleted file mode 100644 index e9eaaac3c..000000000 --- a/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentListFragment.kt +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (C) 2018 - present Instructure, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ package com.instructure.student.AnnotationComments - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatDialog -import androidx.core.content.ContextCompat -import androidx.recyclerview.widget.DefaultItemAnimator -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import com.instructure.annotations.AnnotationDialogs.AnnotationCommentDialog -import com.instructure.annotations.createCommentReplyAnnotation -import com.instructure.annotations.generateAnnotationId -import com.instructure.canvasapi2.managers.CanvaDocsManager -import com.instructure.canvasapi2.models.ApiValues -import com.instructure.canvasapi2.models.DocSession -import com.instructure.canvasapi2.models.canvadocs.CanvaDocAnnotation -import com.instructure.canvasapi2.utils.ApiPrefs -import com.instructure.canvasapi2.utils.weave.awaitApi -import com.instructure.canvasapi2.utils.weave.catch -import com.instructure.canvasapi2.utils.weave.tryWeave -import com.instructure.canvasapi2.utils.weave.weave -import com.instructure.interactions.router.Route -import com.instructure.pandautils.analytics.SCREEN_VIEW_ANNOTATION_COMMENT_LIST -import com.instructure.pandautils.analytics.ScreenView -import com.instructure.pandautils.binding.viewBinding -import com.instructure.pandautils.utils.* -import com.instructure.student.R -import com.instructure.student.databinding.FragmentAnnotationCommentListBinding -import com.instructure.student.fragment.ParentFragment -import com.instructure.student.mobius.assignmentDetails.submissionDetails.content.PdfStudentSubmissionView -import kotlinx.coroutines.Job -import okhttp3.ResponseBody -import org.greenrobot.eventbus.EventBus -import java.util.* - -@ScreenView(SCREEN_VIEW_ANNOTATION_COMMENT_LIST) -class AnnotationCommentListFragment : ParentFragment() { - - private val binding by viewBinding(FragmentAnnotationCommentListBinding::bind) - - private var annotations by ParcelableArrayListArg() - private var assigneeId by LongArg() - private var docSession by ParcelableArg() - private var apiValues by ParcelableArg() - private var headAnnotationId by StringArg() - private var canComment by BooleanArg(true, CAN_COMMENT) - - private var recyclerAdapter: AnnotationCommentListRecyclerAdapter? = null - - private var sendCommentJob: Job? = null - private var editCommentJob: Job? = null - private var deleteCommentJob: Job? = null - - override fun title() = getString(R.string.comments) - - override fun applyTheme() { - with (binding) { - toolbar.title = title() - toolbar.setupAsCloseButton(this@AnnotationCommentListFragment) - ViewStyler.themeToolbarLight(requireActivity(), toolbar) - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = - layoutInflater.inflate(R.layout.fragment_annotation_comment_list, container, false) - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - recyclerAdapter = AnnotationCommentListRecyclerAdapter(requireContext(), docSession, { annotation, position -> - AnnotationCommentDialog.getInstance(requireFragmentManager(), annotation.contents ?: "", requireContext().getString(R.string.editComment)) { cancelled, text -> - if(!cancelled) { - annotation.contents = text - editComment(annotation, position) - } - }.show(requireFragmentManager(), AnnotationCommentDialog::class.java.simpleName) - }, { annotation, position -> - val builder = AlertDialog.Builder(requireContext()) - //we want to show a different title for the root comment - builder.setTitle(R.string.deleteComment) - builder.setMessage(if(position == 0) R.string.deleteHeadCommentConfirmation else R.string.deleteCommentConfirmation) - builder.setPositiveButton(getString(R.string.delete).uppercase(Locale.getDefault())) { _, _ -> - deleteComment(annotation, position) - } - builder.setNegativeButton(getString(R.string.cancel).uppercase(Locale.getDefault()), null) - val dialog = builder.create() - dialog.setOnShowListener { - dialog.getButton(AppCompatDialog.BUTTON_POSITIVE).setTextColor(ThemePrefs.textButtonColor) - dialog.getButton(AppCompatDialog.BUTTON_NEGATIVE).setTextColor(ThemePrefs.textButtonColor) - } - dialog.show() - }) - - configureRecyclerView() - applyTheme() - setupCommentInput() - - if(recyclerAdapter?.size() == 0) { - recyclerAdapter?.addAll(annotations) - } - } - - override fun onDestroyView() { - super.onDestroyView() - sendCommentJob?.cancel() - editCommentJob?.cancel() - deleteCommentJob?.cancel() - EventBus.getDefault().post( - PdfStudentSubmissionView.AnnotationCommentDeleteAcknowledged( - annotations.filter { it.deleted && it.deleteAcknowledged.isNullOrEmpty() }, - assigneeId)) - } - - fun configureRecyclerView() { - val layoutManager = LinearLayoutManager(requireContext()) - layoutManager.orientation = RecyclerView.VERTICAL - binding.annotationCommentsRecyclerView.apply { - this.layoutManager = layoutManager - itemAnimator = DefaultItemAnimator() - adapter = recyclerAdapter - } - } - - private fun setupCommentInput() = with(binding) { - // We want users with read permission to still be able to create and respond to comments. - if(docSession.annotationMetadata?.canRead() == false || !canComment) { - commentInputContainer.setVisible(false) - } else { - sendCommentButton.imageTintList = ViewStyler.generateColorStateList( - intArrayOf(-android.R.attr.state_enabled) to ContextCompat.getColor(requireContext(), R.color.textDark), - intArrayOf() to ThemePrefs.textButtonColor - ) - - sendCommentButton.isEnabled = false - commentEditText.onTextChanged { sendCommentButton.isEnabled = it.isNotBlank() } - sendCommentButton.onClickWithRequireNetwork { - sendComment(commentEditText.text.toString()) - } - } - } - - private fun showSendingStatus() = with(binding) { - sendCommentButton.setInvisible() - sendingProgressBar.setVisible() - sendingProgressBar.announceForAccessibility(getString(R.string.sendingSimple)) - sendingErrorTextView.setGone() - commentEditText.isEnabled = false - } - - private fun hideSendingStatus(success: Boolean) = with(binding) { - sendingProgressBar.setGone() - sendCommentButton.setVisible() - commentEditText.isEnabled = true - if (success) { - commentEditText.setText("") - commentEditText.hideKeyboard() - } else { - sendingErrorTextView.setVisible() - } - } - - - @Suppress("EXPERIMENTAL_FEATURE_WARNING") - private fun sendComment(comment: String) { - sendCommentJob = weave { - try { - showSendingStatus() - //first we need to find the root comment - val rootComment = annotations.firstOrNull() - if (rootComment != null) { - val newCommentReply = awaitApi { CanvaDocsManager.putAnnotation(apiValues.sessionId, generateAnnotationId(), createCommentReplyAnnotation(comment, headAnnotationId, apiValues.documentId, ApiPrefs.user?.id.toString(), rootComment.page), apiValues.canvaDocsDomain, it) } - EventBus.getDefault().post(PdfStudentSubmissionView.AnnotationCommentAdded(newCommentReply, assigneeId)) - // The put request doesn't return this property, so we need to set it to true - newCommentReply.isEditable = true - recyclerAdapter?.add(newCommentReply) //ALSO, add it to the UI - hideSendingStatus(true) - } else { - hideSendingStatus(false) - } - } catch (e: Throwable) { - hideSendingStatus(false) - } - } - } - - @Suppress("EXPERIMENTAL_FEATURE_WARNING") - private fun editComment(annotation: CanvaDocAnnotation, position: Int) { - editCommentJob = tryWeave { - awaitApi { CanvaDocsManager.putAnnotation(apiValues.sessionId, annotation.annotationId, annotation, apiValues.canvaDocsDomain, it) } - EventBus.getDefault().post(PdfStudentSubmissionView.AnnotationCommentEdited(annotation, assigneeId)) - // Update the UI - recyclerAdapter?.add(annotation) - recyclerAdapter?.notifyItemChanged(position) - } catch { - hideSendingStatus(false) - } - } - - @Suppress("EXPERIMENTAL_FEATURE_WARNING") - private fun deleteComment(annotation: CanvaDocAnnotation, position: Int) { - deleteCommentJob = tryWeave { - awaitApi { CanvaDocsManager.deleteAnnotation(apiValues.sessionId, annotation.annotationId, apiValues.canvaDocsDomain, it) } - if(annotation.annotationId == annotations.firstOrNull()?.annotationId) { - //this is the root comment, deleting this deletes the entire thread - EventBus.getDefault().post(PdfStudentSubmissionView.AnnotationCommentDeleted(annotation, true, assigneeId)) - headAnnotationDeleted() - } else { - EventBus.getDefault().post(PdfStudentSubmissionView.AnnotationCommentDeleted(annotation, false, assigneeId)) - recyclerAdapter?.remove(annotation) - recyclerAdapter?.notifyItemChanged(position) - } - } catch { - hideSendingStatus(false) - } - } - - private fun headAnnotationDeleted() { - activity?.onBackPressed() - } - - companion object { - private const val ANNOTATIONS = "annotations" - private const val ASSIGNEE_ID = "assigneeId" - private const val DOC_SESSION = "docSession" - private const val API_VALUES = "apiValues" - private const val HEAD_ANNOTATION_ID = "headAnnotationId" - private const val CAN_COMMENT = "canComment" - - fun newInstance(bundle: Bundle) = AnnotationCommentListFragment().apply { arguments = bundle } - - fun makeRoute(annotations: ArrayList, headAnnotationId: String, docSession: DocSession, apiValues: ApiValues, assigneeId: Long, canComment: Boolean): Route { - val args = makeBundle(annotations, headAnnotationId, docSession, apiValues, assigneeId, canComment) - - return Route(null, AnnotationCommentListFragment::class.java, null, args) - } - - fun validRoute(route: Route): Boolean { - return route.arguments.containsKey(ANNOTATIONS) - && route.arguments.containsKey(HEAD_ANNOTATION_ID) - && route.arguments.containsKey(DOC_SESSION) - && route.arguments.containsKey(API_VALUES) - && route.arguments.containsKey(ASSIGNEE_ID) - } - - fun newInstance(route: Route): AnnotationCommentListFragment? { - if (!validRoute(route)) return null - return AnnotationCommentListFragment().withArgs(route.arguments) - } - - fun makeBundle(annotations: ArrayList, headAnnotationId: String, docSession: DocSession, apiValues: ApiValues, assigneeId: Long, canComment: Boolean): Bundle { - val args = Bundle() - args.putParcelableArrayList(ANNOTATIONS, annotations) - args.putLong(ASSIGNEE_ID, assigneeId) - args.putParcelable(DOC_SESSION, docSession) - args.putParcelable(API_VALUES, apiValues) - args.putString(HEAD_ANNOTATION_ID, headAnnotationId) - args.putBoolean(CAN_COMMENT, canComment) - return args - } - } -} diff --git a/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentListRecyclerAdapter.kt b/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentListRecyclerAdapter.kt deleted file mode 100644 index fae9684f7..000000000 --- a/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentListRecyclerAdapter.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 - present Instructure, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -package com.instructure.student.AnnotationComments - -import android.content.Context -import android.view.View -import com.instructure.canvasapi2.models.DocSession -import com.instructure.canvasapi2.models.canvadocs.CanvaDocAnnotation -import com.instructure.student.adapter.BaseListRecyclerAdapter - -class AnnotationCommentListRecyclerAdapter( - context: Context, - private val docSession: DocSession, - private val editCallback: (CanvaDocAnnotation, Int) -> Unit, - private val deleteCallback: (CanvaDocAnnotation, Int) -> Unit -) : BaseListRecyclerAdapter(context, CanvaDocAnnotation::class.java) { - - init { - itemCallback = object : ItemComparableCallback() { - override fun compare(item1: CanvaDocAnnotation, item2: CanvaDocAnnotation): Int { - val createdAt1 = item1.createdAt - val createdAt2 = item2.createdAt - - return if(createdAt1 != null && createdAt2 != null) { - createdAt1.compareTo(createdAt2) - } else if(createdAt1 != null && createdAt2 == null) { - 1 - } else { - -1 - } - } - } - } - - override fun createViewHolder(v: View, viewType: Int) = AnnotationCommentViewHolder(v) - override fun itemLayoutResId(viewType: Int) = AnnotationCommentViewHolder.holderRes - override fun bindHolder(model: CanvaDocAnnotation, holder: AnnotationCommentViewHolder, position: Int) { - val canDelete = docSession.annotationMetadata?.canManage() ?: false - || (docSession.annotationMetadata?.canWrite() == true && model.userId == docSession.annotationMetadata?.userId) - val canEdit = (docSession.annotationMetadata?.canWrite() == true - && model.userId == docSession.annotationMetadata?.userId) - holder.bind(model, canEdit, canDelete, editCallback, deleteCallback) - } -} diff --git a/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentViewHolder.kt b/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentViewHolder.kt deleted file mode 100644 index 03aca5ef8..000000000 --- a/apps/student/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentViewHolder.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2018 - present Instructure, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -package com.instructure.student.AnnotationComments - -import android.view.Gravity -import android.view.View -import androidx.appcompat.widget.PopupMenu -import androidx.recyclerview.widget.RecyclerView -import com.instructure.canvasapi2.models.canvadocs.CanvaDocAnnotation -import com.instructure.canvasapi2.utils.DateHelper -import com.instructure.pandautils.utils.onClick -import com.instructure.pandautils.utils.setGone -import com.instructure.pandautils.utils.setVisible -import com.instructure.student.R -import com.instructure.student.databinding.ViewholderAnnotationCommentBinding - -class AnnotationCommentViewHolder(view: View) : RecyclerView.ViewHolder(view) { - companion object { - const val holderRes = R.layout.viewholder_annotation_comment - } - - fun bind(annotation: CanvaDocAnnotation, canEdit: Boolean, canDelete: Boolean, editCallback: (CanvaDocAnnotation, Int) -> Unit, deleteCallback: (CanvaDocAnnotation, Int) -> Unit) = with(ViewholderAnnotationCommentBinding.bind(itemView)) { - commentAuthorTextView.text = annotation.userName - commentDateTextView.text = DateHelper.getMonthDayAtTime(root.context, DateHelper.stringToDateWithMillis(annotation.createdAt), root.context.getString(R.string.at)) - commentContentsTextView.text = annotation.contents - - commentEditIcon.setVisible((canEdit || canDelete) && !annotation.deleted) - - if(annotation.deleted) { - commentRemovedLabel.setVisible() - val date = DateHelper.getMonthDayAtTime(root.context, DateHelper.stringToDateWithMillis(annotation.deletedAt), root.context.getString(R.string.at)) - commentRemovedLabel.text = root.resources.getString(R.string.removedComment, date, annotation.deletedBy) - } else { - commentRemovedLabel.setGone() - } - - commentEditIcon.onClick { - val popup = PopupMenu(root.context, it, Gravity.TOP, 0, - R.style.Base_Widget_AppCompat_PopupMenu_Overflow) - popup.inflate(R.menu.menu_edit_annotation_comment) - if(!canEdit) popup.menu.removeItem(R.id.edit) - if(!canDelete) popup.menu.removeItem(R.id.delete) - popup.setOnMenuItemClickListener { - when(it.itemId) { - R.id.edit -> { - editCallback(annotation, adapterPosition) - } - R.id.delete -> { deleteCallback(annotation, adapterPosition) } - } - true - } - popup.show() - } - } -} diff --git a/apps/student/src/main/java/com/instructure/student/activity/CandroidPSPDFActivity.kt b/apps/student/src/main/java/com/instructure/student/activity/CandroidPSPDFActivity.kt deleted file mode 100644 index f29384eb1..000000000 --- a/apps/student/src/main/java/com/instructure/student/activity/CandroidPSPDFActivity.kt +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package com.instructure.student.activity - -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.util.LayoutDirection -import android.util.TypedValue -import android.view.Menu -import android.view.MenuItem -import androidx.annotation.ColorInt -import androidx.core.text.TextUtilsCompat -import com.instructure.annotations.CanvasPdfMenuGrouping -import com.instructure.loginapi.login.dialog.NoInternetConnectionDialog -import com.instructure.pandautils.analytics.SCREEN_VIEW_PSPDFKIT -import com.instructure.pandautils.analytics.ScreenView -import com.instructure.pandautils.features.shareextension.ShareFileSubmissionTarget -import com.instructure.pandautils.utils.Const -import com.instructure.pandautils.utils.NetworkStateProvider -import com.instructure.pandautils.utils.ViewStyler -import com.instructure.student.R -import com.instructure.student.features.shareextension.StudentShareExtensionActivity -import com.pspdfkit.annotations.AnnotationType -import com.pspdfkit.document.processor.PdfProcessorTask -import com.pspdfkit.document.sharing.DefaultDocumentSharingController -import com.pspdfkit.document.sharing.DocumentSharingIntentHelper -import com.pspdfkit.document.sharing.DocumentSharingManager -import com.pspdfkit.document.sharing.SharingOptions -import com.pspdfkit.ui.PdfActivity -import com.pspdfkit.ui.toolbar.AnnotationCreationToolbar -import com.pspdfkit.ui.toolbar.ContextualToolbar -import com.pspdfkit.ui.toolbar.ContextualToolbarMenuItem -import com.pspdfkit.ui.toolbar.ToolbarCoordinatorLayout -import dagger.hilt.android.AndroidEntryPoint -import java.io.File -import java.util.EnumSet -import java.util.Locale -import javax.inject.Inject - -@ScreenView(SCREEN_VIEW_PSPDFKIT) -@AndroidEntryPoint -class CandroidPSPDFActivity : PdfActivity(), ToolbarCoordinatorLayout.OnContextualToolbarLifecycleListener { - override fun onDisplayContextualToolbar(p0: ContextualToolbar<*>) {} - override fun onRemoveContextualToolbar(p0: ContextualToolbar<*>) {} - - private var menuItems: List? = null - - private val submissionTarget by lazy { intent?.extras?.getParcelable(Const.SUBMISSION_TARGET) } - - @Inject - lateinit var networkStateProvider: NetworkStateProvider - - override fun onPrepareContextualToolbar(toolbar: ContextualToolbar<*>) { - if(toolbar is AnnotationCreationToolbar) { - toolbar.setMenuItemGroupingRule(CanvasPdfMenuGrouping(this)) - toolbar.layoutParams = ToolbarCoordinatorLayout.LayoutParams( - ToolbarCoordinatorLayout.LayoutParams.Position.TOP, EnumSet.of(ToolbarCoordinatorLayout.LayoutParams.Position.TOP)) - } - - // We need to reverse the order of the menu items for RTL, once PSPDFKit supports RTL this can be deleted - if (menuItems == null) { - menuItems = toolbar.menuItems - if (TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == LayoutDirection.RTL) { - for (item in menuItems!!) { - if (item.position == ContextualToolbarMenuItem.Position.START) { - item.position = ContextualToolbarMenuItem.Position.END - } else { - item.position = ContextualToolbarMenuItem.Position.START - } - } - if(toolbar.closeButton.position == ContextualToolbarMenuItem.Position.START) { - toolbar.closeButton.position = ContextualToolbarMenuItem.Position.END - } else { - toolbar.closeButton.position = ContextualToolbarMenuItem.Position.START - } - } - } else { - toolbar.menuItems = menuItems as List - } - } - - - override fun onDestroy() { - val path = filesDir.path + intent.data?.path?.replace("/files", "") - document?.let { - val annotations = it.annotationProvider.getAllAnnotationsOfType( - EnumSet.allOf(AnnotationType::class.java) - ) - if (annotations.isEmpty() && networkStateProvider.isOnline()) { - val file = File(path) - if (file.exists()) { - file.delete() - } - } - } - - super.onDestroy() - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setOnContextualToolbarLifecycleListener(this) - - val typedValue = TypedValue() - theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true) - @ColorInt val color = typedValue.data - ViewStyler.setStatusBarDark(this, color) - } - - override fun onCreateOptionsMenu(menu: Menu?): Boolean { - super.onCreateOptionsMenu(menu) - menuInflater.inflate(R.menu.pspdf_activity_menu, menu) - if (submissionTarget != null) { - // If targeted for submission, change the menu item title from "Upload to Canvas" to "Submit Assignment" - val item = menu?.findItem(R.id.upload_item) - item?.title = getString(R.string.submitAssignment) - } - return true - } - - override fun onGetShowAsAction(menuItemId: Int, defaultShowAsAction: Int): Int { - return if (menuItemId != R.id.upload_item) MenuItem.SHOW_AS_ACTION_ALWAYS else super.onGetShowAsAction(menuItemId, defaultShowAsAction) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - super.onOptionsItemSelected(item) - return if (item.itemId == R.id.upload_item) { - uploadDocumentToCanvas() - true - } else { - false - } - } - - private fun uploadDocumentToCanvas() { - if (document != null) { - if (networkStateProvider.isOnline()) { - DocumentSharingManager.shareDocument( - CandroidDocumentSharingController(this, submissionTarget), - document!!, - SharingOptions(PdfProcessorTask.AnnotationProcessingMode.FLATTEN)) - } else { - NoInternetConnectionDialog.show(supportFragmentManager) - } - } - } - - - private inner class CandroidDocumentSharingController( - private val mContext: Context, - private val submissionTarget: ShareFileSubmissionTarget? - ) : DefaultDocumentSharingController(mContext) { - - override fun onDocumentPrepared(shareUri: Uri) { - val intent = Intent(mContext, StudentShareExtensionActivity::class.java) - intent.type = DocumentSharingIntentHelper.MIME_TYPE_PDF - intent.putExtra(Intent.EXTRA_STREAM, shareUri) - intent.putExtra(Const.SUBMISSION_TARGET, submissionTarget) - intent.action = Intent.ACTION_SEND - mContext.startActivity(intent) - } - } -} diff --git a/apps/student/src/main/java/com/instructure/student/features/assignments/details/StudentAssignmentDetailsSubmissionHandler.kt b/apps/student/src/main/java/com/instructure/student/features/assignments/details/StudentAssignmentDetailsSubmissionHandler.kt index 82fba4c1f..fe064efdc 100644 --- a/apps/student/src/main/java/com/instructure/student/features/assignments/details/StudentAssignmentDetailsSubmissionHandler.kt +++ b/apps/student/src/main/java/com/instructure/student/features/assignments/details/StudentAssignmentDetailsSubmissionHandler.kt @@ -134,7 +134,7 @@ class StudentAssignmentDetailsSubmissionHandler( } if (isUploading && submission.errorFlag) { data.value?.attempts = attempts?.toMutableList()?.apply { - if (isNotEmpty()) removeFirst() + if (isNotEmpty()) removeAt(0) add(0, AssignmentDetailsAttemptItemViewModel( AssignmentDetailsAttemptViewData( resources.getString(R.string.attempt, attempts.size), diff --git a/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submission/annnotation/AnnotationSubmissionUploadFragment.kt b/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submission/annnotation/AnnotationSubmissionUploadFragment.kt index d1d16c0c4..2a6b3ea17 100644 --- a/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submission/annnotation/AnnotationSubmissionUploadFragment.kt +++ b/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submission/annnotation/AnnotationSubmissionUploadFragment.kt @@ -71,8 +71,6 @@ class AnnotationSubmissionUploadFragment : BaseCanvasFragment() { PdfStudentSubmissionView( activity = requireActivity(), pdfUrl = it, - fragmentManager = childFragmentManager, - studentAnnotationSubmit = true, courseId = canvasContext.id ) ) diff --git a/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/AnnotationSubmissionViewFragment.kt b/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/AnnotationSubmissionViewFragment.kt index 559db7aa9..613795aaf 100644 --- a/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/AnnotationSubmissionViewFragment.kt +++ b/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/AnnotationSubmissionViewFragment.kt @@ -53,9 +53,7 @@ class AnnotationSubmissionViewFragment : BaseCanvasFragment() { PdfStudentSubmissionView( requireActivity(), it, - courseId, - childFragmentManager, - studentAnnotationView = true, + courseId ) ) } diff --git a/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/PdfStudentSubmissionView.kt b/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/PdfStudentSubmissionView.kt index c3243b460..7eae6c4da 100644 --- a/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/PdfStudentSubmissionView.kt +++ b/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/PdfStudentSubmissionView.kt @@ -17,136 +17,40 @@ package com.instructure.student.mobius.assignmentDetails.submissionDetails.content import android.annotation.SuppressLint -import android.graphics.Color -import android.util.TypedValue -import android.view.Gravity import android.view.LayoutInflater -import android.widget.FrameLayout -import android.widget.ImageView -import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity -import androidx.fragment.app.FragmentManager import com.instructure.annotations.PdfSubmissionView -import com.instructure.canvasapi2.managers.CanvaDocsManager -import com.instructure.canvasapi2.models.ApiValues -import com.instructure.canvasapi2.models.DocSession -import com.instructure.canvasapi2.models.canvadocs.CanvaDocAnnotation -import com.instructure.canvasapi2.utils.Analytics -import com.instructure.canvasapi2.utils.AnalyticsEventConstants -import com.instructure.canvasapi2.utils.ApiPrefs -import com.instructure.canvasapi2.utils.Logger -import com.instructure.canvasapi2.utils.weave.awaitApi -import com.instructure.canvasapi2.utils.weave.catch -import com.instructure.canvasapi2.utils.weave.tryWeave -import com.instructure.loginapi.login.dialog.NoInternetConnectionDialog -import com.instructure.pandautils.utils.onClick -import com.instructure.pandautils.utils.setGone +import com.instructure.canvasapi2.utils.weave.WeaveCoroutine +import com.instructure.pandautils.utils.bind import com.instructure.pandautils.utils.setVisible -import com.instructure.pandautils.views.ProgressiveCanvasLoadingView -import com.instructure.student.AnnotationComments.AnnotationCommentListFragment import com.instructure.student.R import com.instructure.student.databinding.ViewPdfStudentSubmissionBinding -import com.instructure.student.router.RouteMatcher -import com.pspdfkit.preferences.PSPDFKitPreferences -import com.pspdfkit.ui.inspector.PropertyInspectorCoordinatorLayout -import com.pspdfkit.ui.special_mode.manager.AnnotationManager -import com.pspdfkit.ui.toolbar.ToolbarCoordinatorLayout +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import okhttp3.ResponseBody -import org.greenrobot.eventbus.EventBus -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode +import kotlinx.coroutines.launch @SuppressLint("ViewConstructor") class PdfStudentSubmissionView( private val activity: FragmentActivity, private val pdfUrl: String, private val courseId: Long, - private val fragmentManager: FragmentManager, - private val studentAnnotationSubmit: Boolean = false, - private val studentAnnotationView: Boolean = false, + private val studentAnnotationView: Boolean = false + ) : PdfSubmissionView( activity, studentAnnotationView, courseId -), AnnotationManager.OnAnnotationCreationModeChangeListener, AnnotationManager.OnAnnotationEditingModeChangeListener { +) { private val binding: ViewPdfStudentSubmissionBinding - private var initJob: Job? = null - private var deleteJob: Job? = null + override lateinit var pdfContentJob: WeaveCoroutine - override val annotationToolbarLayout: ToolbarCoordinatorLayout - get() = binding.annotationToolbarLayout - override val inspectorCoordinatorLayout: PropertyInspectorCoordinatorLayout - get() = binding.inspectorCoordinatorLayout - override val commentsButton: ImageView - get() = binding.commentsButton - override val loadingContainer: FrameLayout - get() = binding.loadingContainer - override val progressBar: ProgressiveCanvasLoadingView - get() = binding.progressBar + private var initJob: Job? = null override val progressColor: Int get() = R.color.login_studentAppTheme - override fun disableViewPager() {} - override fun enableViewPager() {} - override fun setIsCurrentlyAnnotating(boolean: Boolean) {} - - override fun showAnnotationComments( - commentList: ArrayList, - headAnnotationId: String, - docSession: DocSession, - apiValues: ApiValues - ) { - if (isAttachedToWindow) RouteMatcher.route( - activity, - AnnotationCommentListFragment.makeRoute(commentList, headAnnotationId, docSession, apiValues, ApiPrefs.user!!.id, !studentAnnotationView) - ) - } - - override fun showFileError() { - binding.loadingView.setGone() - binding.retryLoadingContainer.setVisible() - binding.retryLoadingButton.onClick { - setLoading(true) - setup() - } - } - - override fun configureCommentView(commentsButton: ImageView) { - // If we are making annotations position the comments button as we would position in the teacher. - if (studentAnnotationSubmit) { - super.configureCommentView(commentsButton) - return - } - - //we want to offset the comment button by the height of the action bar - val marginDp = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 12f, context.resources.displayMetrics) - val layoutParams = commentsButton.layoutParams as LayoutParams - commentsButton.drawable.setTint(Color.WHITE) - layoutParams.gravity = Gravity.END or Gravity.TOP - layoutParams.topMargin = marginDp.toInt() - layoutParams.rightMargin = marginDp.toInt() - - commentsButton.onClick { - openComments() - } - } - - override fun logOnAnnotationSelectedAnalytics() { - Analytics.logEvent(AnalyticsEventConstants.SUBMISSION_ANNOTATION_SELECTED) - } - - override fun showNoInternetDialog() { - NoInternetConnectionDialog.show(fragmentManager) - } - init { - if (!PSPDFKitPreferences.get(getContext()).isAnnotationCreatorSet) { - PSPDFKitPreferences.get(getContext()).setAnnotationCreator(ApiPrefs.user?.name) - } - binding = ViewPdfStudentSubmissionBinding.inflate(LayoutInflater.from(context), this, true) - setLoading(true) } @@ -157,27 +61,23 @@ class PdfStudentSubmissionView( override fun onAttachedToWindow() { super.onAttachedToWindow() - //we must set up the sliding panel prior to registering to the event - EventBus.getDefault().register(this) - setup() } - override fun attachDocListener() { - // We need to add this flag, because we want to show the toolbar in the student annotation, but hide when - // we open an already submitted file submission with a teacher's annotations. - if (!studentAnnotationSubmit) { - // Modify the session data permissions to make sure students can't annotate already submitted assignments - if (docSession.annotationMetadata?.canWrite() == true) { - docSession.annotationMetadata?.permissions = "read" - } - // Default is to have top inset, remove this since there will be no toolbar - pdfFragment?.setInsets(0, 0, 0, 0) - } - super.attachDocListener() + override fun onFileInitialized() { + binding.openExternallyButton.setText(R.string.utils_openWithAnotherApp) + binding.openExternallyButton.isEnabled = true } fun setup() { + + binding.openExternallyButton.setText(R.string.downloadingInProgress) + binding.openExternallyButton.isEnabled = false + + binding.openExternallyButton.setOnClickListener { + openPdf() + } + handlePdfContent(pdfUrl) setLoading(false) } @@ -185,69 +85,5 @@ class PdfStudentSubmissionView( override fun onDetachedFromWindow() { super.onDetachedFromWindow() initJob?.cancel() - EventBus.getDefault().unregister(this) - } - - - @SuppressLint("CommitTransaction") - override fun setFragment(fragment: Fragment) { - if (isAttachedToWindow) fragmentManager.beginTransaction().replace(binding.content.id, fragment).commitNowAllowingStateLoss() - } - - override fun removeContentFragment() { - val contentFragment = fragmentManager.findFragmentById(binding.content.id) - if (contentFragment != null) { - fragmentManager.beginTransaction().remove(contentFragment).commitAllowingStateLoss() - } } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun onAnnotationCommentAdded(event: AnnotationCommentAdded) { - if (event.assigneeId == ApiPrefs.user!!.id) { - //add the comment to the hashmap - commentRepliesHashMap[event.annotation.inReplyTo]?.add(event.annotation) - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun onAnnotationCommentEdited(event: AnnotationCommentEdited) { - if (event.assigneeId == ApiPrefs.user!!.id) { - //update the annotation in the hashmap - commentRepliesHashMap[event.annotation.inReplyTo]?.find { it.annotationId == event.annotation.annotationId }?.contents = event.annotation.contents - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun onAnnotationCommentDeleted(event: AnnotationCommentDeleted) { - if (event.assigneeId == ApiPrefs.user!!.id) { - if (event.isHeadAnnotation) { - //we need to delete the entire list of comments from the hashmap - commentRepliesHashMap.remove(event.annotation.inReplyTo) - pdfFragment?.selectedAnnotations?.get(0)?.contents = "" - noteHinter?.notifyDrawablesChanged() - } else { - //otherwise just remove the comment - commentRepliesHashMap[event.annotation.inReplyTo]?.remove(event.annotation) - } - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun onAnnotationCommentDeleteAcknowledged(event: AnnotationCommentDeleteAcknowledged) { - if (event.assigneeId == ApiPrefs.user!!.id) { - deleteJob = tryWeave { - for (annotation in event.annotationList) { - awaitApi { CanvaDocsManager.deleteAnnotation(apiValues.sessionId, annotation.annotationId, apiValues.canvaDocsDomain, it) } - commentRepliesHashMap[annotation.inReplyTo]?.remove(annotation) - } - } catch { - Logger.d("There was an error acknowledging the delete!") - } - } - } - - class AnnotationCommentAdded(val annotation: CanvaDocAnnotation, val assigneeId: Long) - class AnnotationCommentEdited(val annotation: CanvaDocAnnotation, val assigneeId: Long) - class AnnotationCommentDeleted(val annotation: CanvaDocAnnotation, val isHeadAnnotation: Boolean, val assigneeId: Long) - class AnnotationCommentDeleteAcknowledged(val annotationList: List, val assigneeId: Long) } \ No newline at end of file diff --git a/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/PdfSubmissionViewFragment.kt b/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/PdfSubmissionViewFragment.kt index 8f1a121ce..b07b77ce3 100644 --- a/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/PdfSubmissionViewFragment.kt +++ b/apps/student/src/main/java/com/instructure/student/mobius/assignmentDetails/submissionDetails/content/PdfSubmissionViewFragment.kt @@ -30,7 +30,7 @@ class PdfSubmissionViewFragment : BaseCanvasFragment() { private var courseId by LongArg() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return PdfStudentSubmissionView(requireActivity(), pdfUrl, courseId, childFragmentManager) + return PdfStudentSubmissionView(requireActivity(), pdfUrl, courseId) } companion object { diff --git a/apps/student/src/main/java/com/instructure/student/router/RouteResolver.kt b/apps/student/src/main/java/com/instructure/student/router/RouteResolver.kt index 0052ea522..ccfc547bd 100644 --- a/apps/student/src/main/java/com/instructure/student/router/RouteResolver.kt +++ b/apps/student/src/main/java/com/instructure/student/router/RouteResolver.kt @@ -27,7 +27,6 @@ import com.instructure.pandautils.features.settings.inboxsignature.InboxSignatur import com.instructure.pandautils.features.smartsearch.SmartSearchFragment import com.instructure.pandautils.fragments.RemoteConfigParamsFragment import com.instructure.pandautils.utils.Const -import com.instructure.student.AnnotationComments.AnnotationCommentListFragment import com.instructure.student.activity.NothingToSeeHereFragment import com.instructure.student.features.coursebrowser.CourseBrowserFragment import com.instructure.student.features.discussion.details.DiscussionDetailsFragment @@ -168,7 +167,6 @@ object RouteResolver { cls.isA() -> UrlSubmissionUploadFragment.newInstance(route) cls.isA() -> PickerSubmissionUploadFragment.newInstance(route) cls.isA() -> UploadStatusSubmissionFragment.newInstance(route) - cls.isA() -> AnnotationCommentListFragment.newInstance(route) cls.isA() -> NothingToSeeHereFragment.newInstance() cls.isA() -> AnnotationSubmissionUploadFragment.newInstance(route) cls.isA() -> PushNotificationPreferencesFragment.newInstance() diff --git a/apps/student/src/main/java/com/instructure/student/util/BaseAppManager.kt b/apps/student/src/main/java/com/instructure/student/util/BaseAppManager.kt index ce30a75ca..1052fdb39 100644 --- a/apps/student/src/main/java/com/instructure/student/util/BaseAppManager.kt +++ b/apps/student/src/main/java/com/instructure/student/util/BaseAppManager.kt @@ -35,10 +35,6 @@ import com.instructure.pandautils.utils.ThemePrefs import com.instructure.student.BuildConfig import com.instructure.student.R import com.instructure.student.activity.NavigationActivity -import com.pspdfkit.PSPDFKit -import com.pspdfkit.exceptions.InvalidPSPDFKitLicenseException -import com.pspdfkit.exceptions.PSPDFKitInitializationFailedException -import com.pspdfkit.initialization.InitializationOptions import com.zynksoftware.documentscanner.ui.DocumentScanner abstract class BaseAppManager : com.instructure.canvasapi2.AppManager(), AnalyticsEventHandling { @@ -61,8 +57,6 @@ abstract class BaseAppManager : com.instructure.canvasapi2.AppManager(), Analyti // Hold off on initializing this until we emit the user properties. RemoteConfigUtils.initialize() - //initPSPDFKit() - initDocumentScanning() if (BuildConfig.DEBUG) { @@ -110,16 +104,6 @@ abstract class BaseAppManager : com.instructure.canvasapi2.AppManager(), Analyti } - private fun initPSPDFKit() { - try { - PSPDFKit.initialize(this, InitializationOptions(licenseKey = BuildConfig.PSPDFKIT_LICENSE_KEY)) - } catch (e: PSPDFKitInitializationFailedException) { - Logger.e("Current device is not compatible with PSPDFKIT!") - } catch (e: InvalidPSPDFKitLicenseException) { - Logger.e("Invalid or Trial PSPDFKIT License!") - } - } - private fun initDocumentScanning() { DocumentScanner.init(this) } diff --git a/apps/student/src/main/java/com/instructure/student/util/FileUtils.kt b/apps/student/src/main/java/com/instructure/student/util/FileUtils.kt index 73fb0b106..5eb0b0b5b 100644 --- a/apps/student/src/main/java/com/instructure/student/util/FileUtils.kt +++ b/apps/student/src/main/java/com/instructure/student/util/FileUtils.kt @@ -20,20 +20,9 @@ package com.instructure.student.util import android.content.Context import android.net.Uri import androidx.annotation.IntegerRes -import com.instructure.canvasapi2.utils.ApiPrefs import com.instructure.pandautils.loaders.OpenMediaAsyncTaskLoader import com.instructure.student.R -import com.instructure.student.activity.CandroidPSPDFActivity import com.instructure.pandautils.features.shareextension.ShareFileSubmissionTarget -import com.pspdfkit.PSPDFKit -import com.pspdfkit.annotations.AnnotationType -import com.pspdfkit.configuration.activity.PdfActivityConfiguration -import com.pspdfkit.configuration.activity.ThumbnailBarMode -import com.pspdfkit.configuration.page.PageFitMode -import com.pspdfkit.configuration.page.PageScrollDirection -import com.pspdfkit.preferences.PSPDFKitPreferences -import com.pspdfkit.ui.PdfActivityIntentBuilder -import com.pspdfkit.ui.special_mode.controller.AnnotationTool object FileUtils { @@ -43,68 +32,7 @@ object FileUtils { context: Context, submissionTarget: ShareFileSubmissionTarget? = null ) { - val annotationCreationList = listOf( - AnnotationTool.INK, - AnnotationTool.HIGHLIGHT, - AnnotationTool.STRIKEOUT, - AnnotationTool.SQUARE, - AnnotationTool.NOTE, - AnnotationTool.FREETEXT, - AnnotationTool.ERASER - ) - - val annotationEditList = listOf( - AnnotationType.INK, - AnnotationType.HIGHLIGHT, - AnnotationType.STRIKEOUT, - AnnotationType.SQUARE, - AnnotationType.NOTE, - AnnotationType.FREETEXT, - AnnotationType.NONE // Wee need this to enable the eraser - ) - if (!PSPDFKitPreferences.get(context).isAnnotationCreatorSet) { - PSPDFKitPreferences.get(context).setAnnotationCreator(ApiPrefs.user?.shortName.orEmpty()) - } - - val pspdfActivityConfiguration: PdfActivityConfiguration - - if (loadedMedia.isSubmission) { - // We don't want to allow users to edit for submission viewing - pspdfActivityConfiguration = PdfActivityConfiguration.Builder(context) - .scrollDirection(PageScrollDirection.HORIZONTAL) - .showThumbnailGrid() - .setThumbnailBarMode(ThumbnailBarMode.THUMBNAIL_BAR_MODE_PINNED) - .disableAnnotationEditing() - .disableAnnotationList() - .disableDocumentEditor() - .fitMode(PageFitMode.FIT_TO_WIDTH) - .build() - } else { - // Standard behavior - pspdfActivityConfiguration = PdfActivityConfiguration.Builder(context) - .scrollDirection(PageScrollDirection.HORIZONTAL) - .showThumbnailGrid() - .setDocumentInfoViewSeparated(false) - .enableDocumentEditor() - .enabledAnnotationTools(annotationCreationList) - .editableAnnotationTypes(annotationEditList) - .fitMode(PageFitMode.FIT_TO_WIDTH) - .build() - } - - if (PSPDFKit.isOpenableUri(context, uri)) { - val intent = PdfActivityIntentBuilder - .fromUri(context, uri) - .configuration(pspdfActivityConfiguration) - .activityClass(CandroidPSPDFActivity::class.java) - .build() - intent.putExtra(com.instructure.pandautils.utils.Const.SUBMISSION_TARGET, submissionTarget) - context.startActivity(intent) - } else { - //If we still can't open this PDF, we will then attempt to pass it off to the user's pdfviewer - context.startActivity(loadedMedia.intent) - } - + context.startActivity(loadedMedia.intent) } @IntegerRes @@ -120,4 +48,6 @@ object FileUtils { } } } + + } diff --git a/apps/student/src/main/res/layout/view_pdf_student_submission.xml b/apps/student/src/main/res/layout/view_pdf_student_submission.xml index 0fae96121..e6487ce64 100644 --- a/apps/student/src/main/res/layout/view_pdf_student_submission.xml +++ b/apps/student/src/main/res/layout/view_pdf_student_submission.xml @@ -29,89 +29,66 @@ app:pclv_indeterminate="true" app:pclv_override_color="@color/login_studentAppTheme"/> - + android:fillViewport="true" + android:visibility="gone" + android:scrollbars="none"> - - - - -