Skip to content

Commit

Permalink
Merge pull request #63 from wordpress-mobile/hackweek/update-target-s…
Browse files Browse the repository at this point in the history
…dk-33

Hack week: Update target SKD to 33
  • Loading branch information
irfano authored Apr 11, 2023
2 parents 087c4c9 + fb56134 commit 0ccb8ab
Show file tree
Hide file tree
Showing 23 changed files with 389 additions and 270 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ subprojects {

ext {
minSdkVersion = 24
compileSdkVersion = 31
targetSdkVersion = 31
compileSdkVersion = 33
targetSdkVersion = 33
buildToolsVersion = "30.0.3"

daggerVersion = gradle.ext.daggerVersion
Expand Down
2 changes: 1 addition & 1 deletion mediapicker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = JavaVersion.VERSION_1_8
}

lintOptions {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package org.wordpress.android.mediapicker.api

import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.annotation.StringRes
import org.wordpress.android.mediapicker.api.MediaPickerSetup.DataSource.CAMERA
import org.wordpress.android.mediapicker.api.MediaPickerSetup.DataSource.DEVICE
import org.wordpress.android.mediapicker.model.MediaType
import org.wordpress.android.mediapicker.model.MediaType.AUDIO
import org.wordpress.android.mediapicker.model.MediaType.IMAGE
import org.wordpress.android.mediapicker.model.MediaType.VIDEO

data class MediaPickerSetup(
val primaryDataSource: DataSource,
val availableDataSources: Set<DataSource>,
val isMultiSelectEnabled: Boolean,
val isStoragePermissionRequired: Boolean,
val allowedTypes: Set<MediaType>,
val areResultsQueued: Boolean,
val searchMode: SearchMode,
val availableDataSources: Set<DataSource> = emptySet(),
val allowedTypes: Set<MediaType> = emptySet(),
@StringRes val title: Int = 0
) {
enum class DataSource {
Expand All @@ -23,12 +28,25 @@ data class MediaPickerSetup(
HIDDEN, VISIBLE_TOGGLED, VISIBLE_UNTOGGLED
}

val isReadStoragePermissionRequired = Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU &&
primaryDataSource == DEVICE

val isImagesPermissionRequired = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
primaryDataSource == DEVICE && allowedTypes.contains(IMAGE)

val isVideoPermissionRequired = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
primaryDataSource == DEVICE && allowedTypes.contains(VIDEO)

val isAudioPermissionRequired = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
primaryDataSource == DEVICE && allowedTypes.contains(AUDIO)

val areMediaPermissionsRequired = isImagesPermissionRequired || isVideoPermissionRequired || isAudioPermissionRequired

fun toBundle(bundle: Bundle) {
bundle.putInt(KEY_PRIMARY_DATA_SOURCE, primaryDataSource.ordinal)
bundle.putIntegerArrayList(KEY_AVAILABLE_DATA_SOURCES, ArrayList(availableDataSources.map { it.ordinal }))
bundle.putIntegerArrayList(KEY_ALLOWED_TYPES, ArrayList(allowedTypes.map { it.ordinal }))
bundle.putBoolean(KEY_CAN_MULTISELECT, isMultiSelectEnabled)
bundle.putBoolean(KEY_REQUIRES_STORAGE_PERMISSIONS, isStoragePermissionRequired)
bundle.putBoolean(KEY_QUEUE_RESULTS, areResultsQueued)
bundle.putInt(KEY_SEARCH_MODE, searchMode.ordinal)
bundle.putInt(KEY_TITLE, title)
Expand All @@ -39,7 +57,6 @@ data class MediaPickerSetup(
intent.putIntegerArrayListExtra(KEY_AVAILABLE_DATA_SOURCES, ArrayList(availableDataSources.map { it.ordinal }))
intent.putIntegerArrayListExtra(KEY_ALLOWED_TYPES, ArrayList(allowedTypes.map { it.ordinal }))
intent.putExtra(KEY_CAN_MULTISELECT, isMultiSelectEnabled)
intent.putExtra(KEY_REQUIRES_STORAGE_PERMISSIONS, isStoragePermissionRequired)
intent.putExtra(KEY_QUEUE_RESULTS, areResultsQueued)
intent.putExtra(KEY_SEARCH_MODE, searchMode.ordinal)
intent.putExtra(KEY_TITLE, title)
Expand All @@ -49,7 +66,6 @@ data class MediaPickerSetup(
private const val KEY_PRIMARY_DATA_SOURCE = "key_primary_data_source"
private const val KEY_AVAILABLE_DATA_SOURCES = "key_available_data_sources"
private const val KEY_CAN_MULTISELECT = "key_can_multiselect"
private const val KEY_REQUIRES_STORAGE_PERMISSIONS = "key_requires_storage_permissions"
private const val KEY_ALLOWED_TYPES = "key_allowed_types"
private const val KEY_QUEUE_RESULTS = "key_queue_results"
private const val KEY_SEARCH_MODE = "key_search_mode"
Expand All @@ -64,18 +80,16 @@ data class MediaPickerSetup(
MediaType.values()[it]
}.toSet()
val multipleSelectionAllowed = bundle.getBoolean(KEY_CAN_MULTISELECT)
val requiresStoragePermissions = bundle.getBoolean(KEY_REQUIRES_STORAGE_PERMISSIONS)
val queueResults = bundle.getBoolean(KEY_QUEUE_RESULTS)
val searchMode = SearchMode.values()[bundle.getInt(KEY_SEARCH_MODE)]
val title = bundle.getInt(KEY_TITLE)
return MediaPickerSetup(
dataSource,
availableDataSources,
multipleSelectionAllowed,
requiresStoragePermissions,
allowedTypes,
queueResults,
searchMode,
availableDataSources,
allowedTypes,
title
)
}
Expand All @@ -92,18 +106,16 @@ data class MediaPickerSetup(
MediaType.values()[it]
}.toSet()
val multipleSelectionAllowed = intent.getBooleanExtra(KEY_CAN_MULTISELECT, false)
val requiresStoragePermissions = intent.getBooleanExtra(KEY_REQUIRES_STORAGE_PERMISSIONS, false)
val queueResults = intent.getBooleanExtra(KEY_QUEUE_RESULTS, false)
val searchMode = SearchMode.values()[intent.getIntExtra(KEY_SEARCH_MODE, 0)]
val title = intent.getIntExtra(KEY_TITLE, 0)
return MediaPickerSetup(
dataSource,
availableDataSources,
multipleSelectionAllowed,
requiresStoragePermissions,
allowedTypes,
queueResults,
searchMode,
availableDataSources,
allowedTypes,
title
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.wordpress.android.mediapicker.model

import org.wordpress.android.mediapicker.model.MediaType.AUDIO
import org.wordpress.android.mediapicker.model.MediaType.IMAGE
import org.wordpress.android.mediapicker.model.MediaType.VIDEO

Expand All @@ -8,5 +9,8 @@ enum class MediaType {
}

enum class MediaTypes(val allowedTypes: Set<MediaType>) {
IMAGES(setOf(IMAGE)), VIDEOS(setOf(VIDEO)), IMAGES_AND_VIDEOS(setOf(IMAGE, VIDEO))
IMAGES(setOf(IMAGE)),
VIDEOS(setOf(VIDEO)),
IMAGES_AND_VIDEOS(setOf(IMAGE, VIDEO)),
EVERYTHING(setOf(IMAGE, VIDEO, AUDIO))
}
Original file line number Diff line number Diff line change
@@ -1,51 +1,41 @@
package org.wordpress.android.mediapicker.source.device

import android.os.Build
import org.wordpress.android.mediapicker.api.MediaPickerSetup
import org.wordpress.android.mediapicker.api.MediaPickerSetup.DataSource.CAMERA
import org.wordpress.android.mediapicker.api.MediaPickerSetup.DataSource.DEVICE
import org.wordpress.android.mediapicker.api.MediaPickerSetup.DataSource.SYSTEM_PICKER
import org.wordpress.android.mediapicker.api.MediaPickerSetup.SearchMode.HIDDEN
import org.wordpress.android.mediapicker.api.MediaPickerSetup.SearchMode.VISIBLE_UNTOGGLED
import org.wordpress.android.mediapicker.model.MediaType.IMAGE
import org.wordpress.android.mediapicker.model.MediaTypes

class DeviceMediaPickerSetup private constructor() {
companion object {
fun buildMediaPicker(mediaTypes: MediaTypes, canMultiSelect: Boolean): MediaPickerSetup {
return MediaPickerSetup(
primaryDataSource = DEVICE,
availableDataSources = setOf(SYSTEM_PICKER),
isMultiSelectEnabled = canMultiSelect,
isStoragePermissionRequired = true,
allowedTypes = mediaTypes.allowedTypes,
areResultsQueued = false,
searchMode = VISIBLE_UNTOGGLED,
availableDataSources = setOf(CAMERA, SYSTEM_PICKER),
allowedTypes = mediaTypes.allowedTypes,
title = R.string.photo_picker_title
)
}

fun buildSystemPicker(mediaTypes: MediaTypes, canMultiSelect: Boolean): MediaPickerSetup {
return MediaPickerSetup(
primaryDataSource = SYSTEM_PICKER,
availableDataSources = emptySet(),
isMultiSelectEnabled = canMultiSelect,
isStoragePermissionRequired = false,
allowedTypes = mediaTypes.allowedTypes,
areResultsQueued = false,
searchMode = HIDDEN
searchMode = HIDDEN,
allowedTypes = mediaTypes.allowedTypes
)
}

// Storage permission isn't required for Android API 29+ because there is a new storage
// access concept - a scoped storage
fun buildCameraPicker(): MediaPickerSetup {
return MediaPickerSetup(
primaryDataSource = CAMERA,
availableDataSources = emptySet(),
isMultiSelectEnabled = false,
isStoragePermissionRequired = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q,
allowedTypes = setOf(IMAGE),
areResultsQueued = false,
searchMode = HIDDEN
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ class GifMediaPickerSetup private constructor() {
fun build(canMultiSelect: Boolean): MediaPickerSetup {
return MediaPickerSetup(
primaryDataSource = GIF_LIBRARY,
availableDataSources = emptySet(),
isMultiSelectEnabled = canMultiSelect,
isStoragePermissionRequired = false,
allowedTypes = setOf(IMAGE),
areResultsQueued = false,
searchMode = VISIBLE_TOGGLED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ class MediaLibraryPickerSetup private constructor() {
fun build(mediaTypes: MediaTypes, canMultiSelect: Boolean): MediaPickerSetup {
return MediaPickerSetup(
primaryDataSource = WP_MEDIA_LIBRARY,
availableDataSources = emptySet(),
isMultiSelectEnabled = canMultiSelect,
isStoragePermissionRequired = false,
allowedTypes = mediaTypes.allowedTypes,
areResultsQueued = false,
searchMode = HIDDEN,
Expand Down
5 changes: 4 additions & 1 deletion mediapicker/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.wordpress.android.mediapicker">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />

<queries>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ internal class MediaPickerTracker @Inject constructor(

fun trackShowPermissionsScreen(
mediaPickerSetup: MediaPickerSetup,
permission: PermissionsRequested,
permissions: List<PermissionsRequested>,
isAlwaysDenied: Boolean
) {
val properties = mediaPickerSetup.toProperties()
properties["always_denied"] = isAlwaysDenied
properties["permission_requested"] = permission.name
properties["permission_requested"] = permissions.joinToString { it.name }
tracker.track(MEDIA_PICKER_SHOW_PERMISSIONS_SCREEN, properties)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ internal class Permissions @Inject constructor(
) {
companion object {
val PERMISSION_STORAGE_READ = booleanPreferencesKey("PERMISSION_STORAGE_READ")
val PERMISSION_STORAGE_WRITE = booleanPreferencesKey("PERMISSION_STORAGE_WRITE")
val PERMISSION_CAMERA = booleanPreferencesKey("PERMISSION_CAMERA")
val PERMISSION_IMAGES_READ = booleanPreferencesKey("PERMISSION_IMAGES_READ")
val PERMISSION_VIDEO_READ = booleanPreferencesKey("PERMISSION_VIDEO_READ")
val PERMISSION_AUDIO_READ = booleanPreferencesKey("PERMISSION_AUDIO_READ")
}

private val Context.dataStore: DataStore<Preferences> by preferencesDataStore("permissions")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.wordpress.android.mediapicker.model

import android.net.Uri
import org.wordpress.android.mediapicker.model.MediaItem.Identifier
import org.wordpress.android.mediapicker.model.UiStateModels.PermissionsRequested

internal sealed class MediaNavigationEvent {
data class PreviewUrl(val url: String) : MediaNavigationEvent()
Expand All @@ -14,5 +15,10 @@ internal sealed class MediaNavigationEvent {
object Exit : MediaNavigationEvent()
object ShowAppSettings : MediaNavigationEvent()
object RequestStoragePermission : MediaNavigationEvent()
object RequestCameraPermission : MediaNavigationEvent()
data class RequestCameraPermission(
val permissions: List<PermissionsRequested>
) : MediaNavigationEvent()
data class RequestMediaPermissions(
val permissions: List<PermissionsRequested>
) : MediaNavigationEvent()
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package org.wordpress.android.mediapicker.model

import android.Manifest
import android.Manifest.permission
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import org.wordpress.android.mediapicker.api.MediaPickerSetup.DataSource
import org.wordpress.android.mediapicker.model.UiStateModels.PermissionsRequested.STORAGE
import org.wordpress.android.mediapicker.model.MediaType.AUDIO
import org.wordpress.android.mediapicker.model.MediaType.IMAGE
import org.wordpress.android.mediapicker.model.MediaType.VIDEO
import org.wordpress.android.mediapicker.model.UiString.UiStringRes

internal class UiStateModels {
Expand Down Expand Up @@ -66,11 +72,58 @@ internal class UiStateModels {
@Parcelize
data class SoftAskRequest(
val show: Boolean,
val type: PermissionsRequested = STORAGE,
val permissions: List<PermissionsRequested> = emptyList(),
val isAlwaysDenied: Boolean = false,
) : Parcelable

enum class PermissionsRequested {
CAMERA, STORAGE
CAMERA, READ_STORAGE, WRITE_STORAGE, IMAGES, VIDEOS, MUSIC;

companion object {
fun fromString(permission: String): PermissionsRequested {
return when (permission) {
Manifest.permission.CAMERA -> CAMERA
Manifest.permission.READ_EXTERNAL_STORAGE -> READ_STORAGE
Manifest.permission.WRITE_EXTERNAL_STORAGE -> WRITE_STORAGE
Manifest.permission.READ_MEDIA_IMAGES -> IMAGES
Manifest.permission.READ_MEDIA_VIDEO -> VIDEOS
Manifest.permission.READ_MEDIA_AUDIO -> MUSIC
else -> throw UnsupportedOperationException("Unsupported permission: $permission")
}
}

fun fromMediaType(type: MediaType): PermissionsRequested {
return when (type) {
IMAGE -> IMAGES
VIDEO -> VIDEOS
AUDIO -> MUSIC
else -> throw UnsupportedOperationException("Unsupported media type: $type")
}
}
}

@Suppress("ExceptionRaisedInUnexpectedLocation")
override fun toString(): String {
return when (this) {
CAMERA -> permission.CAMERA
READ_STORAGE -> permission.READ_EXTERNAL_STORAGE
WRITE_STORAGE -> permission.WRITE_EXTERNAL_STORAGE
IMAGES -> if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
permission.READ_MEDIA_IMAGES
} else {
throw UnsupportedOperationException("Unsupported permission: $this")
}
VIDEOS -> if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
permission.READ_MEDIA_VIDEO
} else {
throw UnsupportedOperationException("Unsupported permission: $this")
}
MUSIC -> if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
permission.READ_MEDIA_AUDIO
} else {
throw UnsupportedOperationException("Unsupported permission: $this")
}
}
}
}
}
Loading

0 comments on commit 0ccb8ab

Please sign in to comment.