1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.intentresolver.contentpreview
18 
19 import android.app.Application
20 import android.content.ContentResolver
21 import android.content.Intent
22 import android.net.Uri
23 import androidx.annotation.MainThread
24 import androidx.lifecycle.ViewModel
25 import androidx.lifecycle.ViewModelProvider
26 import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
27 import androidx.lifecycle.viewModelScope
28 import androidx.lifecycle.viewmodel.CreationExtras
29 import com.android.intentresolver.R
30 import com.android.intentresolver.inject.Background
31 import kotlinx.coroutines.CoroutineDispatcher
32 import kotlinx.coroutines.Dispatchers
33 import kotlinx.coroutines.plus
34 
35 /** A view model for the preview logic */
36 class PreviewViewModel(
37     private val contentResolver: ContentResolver,
38     // TODO: inject ImageLoader instead
39     private val thumbnailSize: Int,
40     @Background private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
41 ) : BasePreviewViewModel() {
42     private var targetIntent: Intent? = null
43     private var additionalContentUri: Uri? = null
44     private var isPayloadTogglingEnabled = false
45 
<lambda>null46     override val previewDataProvider by lazy {
47         val targetIntent = requireNotNull(this.targetIntent) { "Not initialized" }
48         PreviewDataProvider(
49             viewModelScope + dispatcher,
50             targetIntent,
51             additionalContentUri,
52             contentResolver,
53             isPayloadTogglingEnabled,
54         )
55     }
56 
<lambda>null57     override val imageLoader by lazy {
58         ImagePreviewImageLoader(
59             viewModelScope + dispatcher,
60             thumbnailSize,
61             contentResolver,
62             cacheSize = 16
63         )
64     }
65 
66     // TODO: make the view model injectable and inject these dependencies instead
67     @MainThread
initnull68     override fun init(
69         targetIntent: Intent,
70         additionalContentUri: Uri?,
71         isPayloadTogglingEnabled: Boolean,
72     ) {
73         if (this.targetIntent != null) return
74         this.targetIntent = targetIntent
75         this.additionalContentUri = additionalContentUri
76         this.isPayloadTogglingEnabled = isPayloadTogglingEnabled
77     }
78 
79     companion object {
80         val Factory: ViewModelProvider.Factory =
81             object : ViewModelProvider.Factory {
82                 @Suppress("UNCHECKED_CAST")
createnull83                 override fun <T : ViewModel> create(
84                     modelClass: Class<T>,
85                     extras: CreationExtras
86                 ): T {
87                     val application: Application = checkNotNull(extras[APPLICATION_KEY])
88                     return PreviewViewModel(
89                         application.contentResolver,
90                         application.resources.getDimensionPixelSize(
91                             R.dimen.chooser_preview_image_max_dimen
92                         )
93                     )
94                         as T
95                 }
96             }
97     }
98 }
99