Initial implementation of multipicker.
This commit is contained in:
parent
08cfe79625
commit
6db0de321c
|
@ -14,3 +14,137 @@
|
|||
/tmp
|
||||
|
||||
ktlint
|
||||
multipicker/build/.transforms/3e0e90edbb388b6989e862c9faf75e87.bin
|
||||
multipicker/build/.transforms/55ef863ef687bb455ca3376fbf042ba5.bin
|
||||
multipicker/build/.transforms/3e0e90edbb388b6989e862c9faf75e87/classes/classes.dex
|
||||
multipicker/build/.transforms/55ef863ef687bb455ca3376fbf042ba5/classes/classes.dex
|
||||
multipicker/build/generated/source/buildConfig/debug/im/vector/riotx/multipicker/BuildConfig.java
|
||||
multipicker/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml
|
||||
multipicker/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output.json
|
||||
multipicker/build/intermediates/annotation_processor_list/debug/annotationProcessors.json
|
||||
multipicker/build/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt
|
||||
multipicker/build/intermediates/compile_library_classes/debug/classes.jar
|
||||
multipicker/build/intermediates/compile_only_not_namespaced_r_class_jar/debug/R.jar
|
||||
multipicker/build/intermediates/consumer_proguard_file/debug/proguard.txt
|
||||
multipicker/build/intermediates/incremental/debug-mergeJavaRes/merge-state
|
||||
multipicker/build/intermediates/incremental/debug-mergeNativeLibs/merge-state
|
||||
multipicker/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml
|
||||
multipicker/build/intermediates/incremental/mergeDebugShaders/merger.xml
|
||||
multipicker/build/intermediates/incremental/packageDebugAssets/merger.xml
|
||||
multipicker/build/intermediates/incremental/packageDebugResources/compile-file-map.properties
|
||||
multipicker/build/intermediates/incremental/packageDebugResources/merger.xml
|
||||
multipicker/build/intermediates/javac/debug/classes/im/vector/riotx/multipicker/BuildConfig.class
|
||||
multipicker/build/intermediates/library_java_res/debug/res.jar
|
||||
multipicker/build/intermediates/library_manifest/debug/AndroidManifest.xml
|
||||
multipicker/build/intermediates/local_only_symbol_list/debug/parseDebugLibraryResources/R-def.txt
|
||||
multipicker/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt
|
||||
multipicker/build/intermediates/merged_java_res/debug/out.jar
|
||||
multipicker/build/intermediates/merged_manifests/debug/output.json
|
||||
multipicker/build/intermediates/packaged-classes/debug/classes.jar
|
||||
multipicker/build/intermediates/res/symbol-table-with-package/debug/package-aware-r.txt
|
||||
multipicker/build/intermediates/runtime_library_classes/debug/classes.jar
|
||||
multipicker/build/intermediates/symbols/debug/R.txt
|
||||
multipicker/build/kotlin/compileDebugKotlin/build-history.bin
|
||||
multipicker/build/kotlin/compileDebugKotlin/last-build.bin
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/inputs/source-to-output.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/inputs/source-to-output.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/inputs/source-to-output.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/inputs/source-to-output.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/inputs/source-to-output.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/inputs/source-to-output.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/inputs/source-to-output.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/constants.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/constants.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/constants.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/constants.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/constants.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/constants.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/constants.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/proto.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/proto.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/proto.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/proto.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/proto.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/proto.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/proto.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/subtypes.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/subtypes.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/subtypes.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/subtypes.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/subtypes.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/subtypes.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/supertypes.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/supertypes.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/supertypes.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/supertypes.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/supertypes.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/jvm/kotlin/supertypes.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/counters.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/file-to-id.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/file-to-id.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/file-to-id.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/file-to-id.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/file-to-id.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/file-to-id.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/file-to-id.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/id-to-file.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/id-to-file.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/id-to-file.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/id-to-file.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/id-to-file.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/id-to-file.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/id-to-file.tab_i.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab.keystream
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab.keystream.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab.len
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab.values
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab.values.at
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab.values.s
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab_i
|
||||
multipicker/build/kotlin/compileDebugKotlin/caches-jvm/lookups/lookups.tab_i.len
|
||||
multipicker/build/outputs/aar/multipicker-debug.aar
|
||||
multipicker/build/outputs/logs/manifest-merger-debug-report.txt
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/AudioPicker.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/ContactPicker.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/FilePicker.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/ImagePicker.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/MultiPicker$Type$AUDIO$2.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/MultiPicker$Type$CONTACT$2.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/MultiPicker$Type$FILE$2.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/MultiPicker$Type$IMAGE$2.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/MultiPicker$Type$VIDEO$2.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/MultiPicker$Type.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/MultiPicker.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/Picker.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/VideoPicker.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/entity/MultiPickerAudioType.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/entity/MultiPickerBaseType.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/entity/MultiPickerContactType.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/entity/MultiPickerFileType.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/entity/MultiPickerImageType.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/im/vector/riotx/multipicker/entity/MultiPickerVideoType.class
|
||||
multipicker/build/tmp/kotlin-classes/debug/META-INF/multipicker_debug.kotlin_module
|
||||
|
|
|
@ -119,7 +119,7 @@ dependencies {
|
|||
implementation "ru.noties.markwon:core:$markwon_version"
|
||||
|
||||
// Image
|
||||
implementation 'androidx.exifinterface:exifinterface:1.1.0'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.0-alpha01'
|
||||
implementation 'id.zelory:compressor:3.0.0'
|
||||
|
||||
// Database
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.3"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.0-alpha01'
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import junit.framework.Assert.assertEquals
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("im.vector.riotx.multipicker.test", appContext.packageName)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="im.vector.riotx.multipicker" />
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import androidx.fragment.app.Fragment
|
||||
import im.vector.riotx.multipicker.entity.MultiPickerAudioType
|
||||
|
||||
class AudioPicker(override val requestCode: Int) : Picker<MultiPickerAudioType>(requestCode) {
|
||||
|
||||
override fun startWith(activity: Activity) {
|
||||
activity.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun startWith(fragment: Fragment) {
|
||||
fragment.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerAudioType> {
|
||||
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val audioList = mutableListOf<MultiPickerAudioType>()
|
||||
|
||||
val selectedUriList = mutableListOf<Uri>()
|
||||
val dataUri = data?.data
|
||||
val clipData = data?.clipData
|
||||
|
||||
if (clipData != null) {
|
||||
for (i in 0 until clipData.itemCount) {
|
||||
selectedUriList.add(clipData.getItemAt(i).uri)
|
||||
}
|
||||
} else if (dataUri != null) {
|
||||
selectedUriList.add(dataUri)
|
||||
}
|
||||
|
||||
selectedUriList.forEach { selectedUri ->
|
||||
val projection = arrayOf(
|
||||
MediaStore.Audio.Media.DISPLAY_NAME,
|
||||
MediaStore.Audio.Media.SIZE
|
||||
)
|
||||
|
||||
context.contentResolver.query(
|
||||
selectedUri,
|
||||
projection,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)?.use { cursor ->
|
||||
val nameColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)
|
||||
val sizeColumn = cursor.getColumnIndex(MediaStore.Audio.Media.SIZE)
|
||||
|
||||
if (cursor.moveToNext()) {
|
||||
val name = cursor.getString(nameColumn)
|
||||
val size = cursor.getLong(sizeColumn)
|
||||
var duration = 0L
|
||||
|
||||
context.contentResolver.openFileDescriptor(selectedUri, "r")?.use { pfd ->
|
||||
val mediaMetadataRetriever = MediaMetadataRetriever()
|
||||
mediaMetadataRetriever.setDataSource(pfd.fileDescriptor)
|
||||
duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toLong()
|
||||
}
|
||||
|
||||
audioList.add(
|
||||
MultiPickerAudioType(
|
||||
name,
|
||||
size,
|
||||
context.contentResolver.getType(selectedUri),
|
||||
selectedUri,
|
||||
duration
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return audioList
|
||||
}
|
||||
|
||||
private fun createIntent(): Intent {
|
||||
return Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, !single)
|
||||
type = "audio/*"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.provider.ContactsContract
|
||||
import androidx.fragment.app.Fragment
|
||||
import im.vector.riotx.multipicker.entity.MultiPickerContactType
|
||||
|
||||
class ContactPicker(override val requestCode: Int) : Picker<MultiPickerContactType>(requestCode) {
|
||||
|
||||
override fun startWith(activity: Activity) {
|
||||
activity.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun startWith(fragment: Fragment) {
|
||||
fragment.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerContactType> {
|
||||
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val contactList = mutableListOf<MultiPickerContactType>()
|
||||
|
||||
data?.data?.let { selectedUri ->
|
||||
val projection = arrayOf(
|
||||
ContactsContract.Contacts.DISPLAY_NAME,
|
||||
ContactsContract.Contacts.PHOTO_URI,
|
||||
ContactsContract.Contacts._ID
|
||||
)
|
||||
|
||||
context.contentResolver.query(
|
||||
selectedUri,
|
||||
projection,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
val idColumn = cursor.getColumnIndex(ContactsContract.Contacts._ID)
|
||||
val nameColumn = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
|
||||
val photoUriColumn = cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)
|
||||
|
||||
val contactId = cursor.getInt(idColumn)
|
||||
var name = cursor.getString(nameColumn)
|
||||
var photoUri = cursor.getString(photoUriColumn)
|
||||
var phoneNumberList = mutableListOf<String>()
|
||||
var emailList = mutableListOf<String>()
|
||||
|
||||
getRawContactId(context.contentResolver, contactId)?.let { rawContactId ->
|
||||
val selection = ContactsContract.Data.RAW_CONTACT_ID + " = ?"
|
||||
val selectionArgs = arrayOf(rawContactId.toString())
|
||||
|
||||
context.contentResolver.query(
|
||||
ContactsContract.Data.CONTENT_URI,
|
||||
arrayOf(
|
||||
ContactsContract.Data.MIMETYPE,
|
||||
ContactsContract.Data.DATA1
|
||||
),
|
||||
selection,
|
||||
selectionArgs,
|
||||
null
|
||||
)?.use { cursor ->
|
||||
while (cursor.moveToNext()) {
|
||||
val mimeType = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE))
|
||||
val contactData = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DATA1))
|
||||
|
||||
if (mimeType == ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) {
|
||||
name = contactData
|
||||
}
|
||||
if (mimeType == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) {
|
||||
phoneNumberList.add(contactData)
|
||||
}
|
||||
if (mimeType == ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) {
|
||||
emailList.add(contactData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
contactList.add(
|
||||
MultiPickerContactType(
|
||||
name,
|
||||
photoUri,
|
||||
phoneNumberList,
|
||||
emailList
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return contactList
|
||||
}
|
||||
|
||||
private fun getRawContactId(contentResolver: ContentResolver, contactId: Int): Int? {
|
||||
val projection = arrayOf(ContactsContract.RawContacts._ID)
|
||||
val selection = ContactsContract.RawContacts.CONTACT_ID + " = ?"
|
||||
val selectionArgs = arrayOf(contactId.toString() + "")
|
||||
return contentResolver.query(
|
||||
ContactsContract.RawContacts.CONTENT_URI,
|
||||
projection,
|
||||
selection,
|
||||
selectionArgs,
|
||||
null
|
||||
)?.use { cursor ->
|
||||
return if (cursor.moveToFirst()) cursor.getInt(cursor.getColumnIndex(ContactsContract.RawContacts._ID)) else null
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIntent(): Intent {
|
||||
return Intent(Intent.ACTION_PICK).apply {
|
||||
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, !single)
|
||||
type = ContactsContract.Contacts.CONTENT_TYPE
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.provider.OpenableColumns
|
||||
import androidx.fragment.app.Fragment
|
||||
import im.vector.riotx.multipicker.entity.MultiPickerFileType
|
||||
|
||||
class FilePicker(override val requestCode: Int) : Picker<MultiPickerFileType>(requestCode) {
|
||||
|
||||
override fun startWith(activity: Activity) {
|
||||
activity.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun startWith(fragment: Fragment) {
|
||||
fragment.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerFileType> {
|
||||
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val fileList = mutableListOf<MultiPickerFileType>()
|
||||
|
||||
val selectedUriList = mutableListOf<Uri>()
|
||||
val dataUri = data?.data
|
||||
val clipData = data?.clipData
|
||||
|
||||
if (clipData != null) {
|
||||
for (i in 0 until clipData.itemCount) {
|
||||
selectedUriList.add(clipData.getItemAt(i).uri)
|
||||
}
|
||||
} else if (dataUri != null) {
|
||||
selectedUriList.add(dataUri)
|
||||
}
|
||||
|
||||
selectedUriList.forEach { selectedUri ->
|
||||
context.contentResolver.query(selectedUri, null, null, null, null)
|
||||
?.use { cursor ->
|
||||
val nameColumn = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
||||
val sizeColumn = cursor.getColumnIndex(OpenableColumns.SIZE)
|
||||
if (cursor.moveToFirst()) {
|
||||
val name = cursor.getString(nameColumn)
|
||||
val size = cursor.getLong(sizeColumn)
|
||||
|
||||
fileList.add(
|
||||
MultiPickerFileType(
|
||||
name,
|
||||
size,
|
||||
context.contentResolver.getType(selectedUri),
|
||||
selectedUri
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileList
|
||||
}
|
||||
|
||||
private fun createIntent(): Intent {
|
||||
return Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, !single)
|
||||
type = "*/*"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.ImageDecoder
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.MediaStore
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import androidx.fragment.app.Fragment
|
||||
import im.vector.riotx.multipicker.entity.MultiPickerImageType
|
||||
|
||||
class ImagePicker(override val requestCode: Int) : Picker<MultiPickerImageType>(requestCode) {
|
||||
|
||||
override fun startWith(activity: Activity) {
|
||||
activity.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun startWith(fragment: Fragment) {
|
||||
fragment.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerImageType> {
|
||||
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val imageList = mutableListOf<MultiPickerImageType>()
|
||||
|
||||
val selectedUriList = mutableListOf<Uri>()
|
||||
val dataUri = data?.data
|
||||
val clipData = data?.clipData
|
||||
|
||||
if (clipData != null) {
|
||||
for (i in 0 until clipData.itemCount) {
|
||||
selectedUriList.add(clipData.getItemAt(i).uri)
|
||||
}
|
||||
} else if (dataUri != null) {
|
||||
selectedUriList.add(dataUri)
|
||||
}
|
||||
|
||||
selectedUriList.forEach { selectedUri ->
|
||||
val projection = arrayOf(
|
||||
MediaStore.Images.Media.DISPLAY_NAME,
|
||||
MediaStore.Images.Media.SIZE
|
||||
)
|
||||
|
||||
context.contentResolver.query(
|
||||
selectedUri,
|
||||
projection,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)?.use { cursor ->
|
||||
val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
|
||||
val sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE)
|
||||
|
||||
if (cursor.moveToNext()) {
|
||||
val name = cursor.getString(nameColumn)
|
||||
val size = cursor.getLong(sizeColumn)
|
||||
|
||||
var orientation = 0
|
||||
|
||||
val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, selectedUri))
|
||||
} else {
|
||||
context.contentResolver.openInputStream(selectedUri)?.use { inputStream ->
|
||||
BitmapFactory.decodeStream(inputStream)
|
||||
}
|
||||
}
|
||||
|
||||
context.contentResolver.openInputStream(selectedUri)?.use { inputStream ->
|
||||
try {
|
||||
ExifInterface(inputStream).let {
|
||||
orientation = it.rotationDegrees
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
imageList.add(
|
||||
MultiPickerImageType(
|
||||
name,
|
||||
size,
|
||||
context.contentResolver.getType(selectedUri),
|
||||
selectedUri,
|
||||
bitmap?.width ?: 0,
|
||||
bitmap?.height ?: 0,
|
||||
orientation
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return imageList
|
||||
}
|
||||
|
||||
private fun createIntent(): Intent {
|
||||
return Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, !single)
|
||||
type = "image/*"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
class MultiPicker<T> {
|
||||
|
||||
companion object Type {
|
||||
val IMAGE by lazy { MultiPicker<ImagePicker>() }
|
||||
val FILE by lazy { MultiPicker<FilePicker>() }
|
||||
val VIDEO by lazy { MultiPicker<VideoPicker>() }
|
||||
val AUDIO by lazy { MultiPicker<AudioPicker>() }
|
||||
val CONTACT by lazy { MultiPicker<ContactPicker>() }
|
||||
|
||||
const val REQUEST_CODE_PICK_IMAGE = 5000
|
||||
const val REQUEST_CODE_PICK_VIDEO = 5001
|
||||
const val REQUEST_CODE_PICK_FILE = 5002
|
||||
const val REQUEST_CODE_PICK_AUDIO = 5003
|
||||
const val REQUEST_CODE_PICK_CONTACT = 5004
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T> get(type: MultiPicker<T>): T {
|
||||
return when (type) {
|
||||
IMAGE -> ImagePicker(REQUEST_CODE_PICK_IMAGE) as T
|
||||
VIDEO -> VideoPicker(REQUEST_CODE_PICK_VIDEO) as T
|
||||
FILE -> FilePicker(REQUEST_CODE_PICK_FILE) as T
|
||||
AUDIO -> AudioPicker(REQUEST_CODE_PICK_AUDIO) as T
|
||||
CONTACT -> ContactPicker(REQUEST_CODE_PICK_CONTACT) as T
|
||||
else -> throw IllegalArgumentException("Unsupported type $type")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
abstract class Picker<T>(open val requestCode: Int) {
|
||||
|
||||
protected var single = false
|
||||
|
||||
abstract fun startWith(activity: Activity)
|
||||
|
||||
abstract fun startWith(fragment: Fragment)
|
||||
|
||||
abstract fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<T>
|
||||
|
||||
fun single(): Picker<T> {
|
||||
single = true
|
||||
return this
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import androidx.fragment.app.Fragment
|
||||
import im.vector.riotx.multipicker.entity.MultiPickerVideoType
|
||||
|
||||
class VideoPicker(override val requestCode: Int) : Picker<MultiPickerVideoType>(requestCode) {
|
||||
|
||||
override fun startWith(activity: Activity) {
|
||||
activity.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun startWith(fragment: Fragment) {
|
||||
fragment.startActivityForResult(createIntent(), requestCode)
|
||||
}
|
||||
|
||||
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerVideoType> {
|
||||
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val videoList = mutableListOf<MultiPickerVideoType>()
|
||||
|
||||
val selectedUriList = mutableListOf<Uri>()
|
||||
val dataUri = data?.data
|
||||
val clipData = data?.clipData
|
||||
|
||||
if (clipData != null) {
|
||||
for (i in 0 until clipData.itemCount) {
|
||||
selectedUriList.add(clipData.getItemAt(i).uri)
|
||||
}
|
||||
} else if (dataUri != null) {
|
||||
selectedUriList.add(dataUri)
|
||||
}
|
||||
|
||||
selectedUriList.forEach { selectedUri ->
|
||||
val projection = arrayOf(
|
||||
MediaStore.Video.Media.DISPLAY_NAME,
|
||||
MediaStore.Video.Media.SIZE
|
||||
)
|
||||
|
||||
context.contentResolver.query(
|
||||
selectedUri,
|
||||
projection,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)?.use { cursor ->
|
||||
val nameColumn = cursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME)
|
||||
val sizeColumn = cursor.getColumnIndex(MediaStore.Video.Media.SIZE)
|
||||
|
||||
if (cursor.moveToNext()) {
|
||||
val name = cursor.getString(nameColumn)
|
||||
val size = cursor.getLong(sizeColumn)
|
||||
var duration = 0L
|
||||
var width = 0
|
||||
var height = 0
|
||||
var orientation = 0
|
||||
|
||||
context.contentResolver.openFileDescriptor(selectedUri, "r")?.use { pfd ->
|
||||
val mediaMetadataRetriever = MediaMetadataRetriever()
|
||||
mediaMetadataRetriever.setDataSource(pfd.fileDescriptor)
|
||||
duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toLong()
|
||||
width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH).toInt()
|
||||
height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT).toInt()
|
||||
orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION).toInt()
|
||||
}
|
||||
|
||||
videoList.add(
|
||||
MultiPickerVideoType(
|
||||
name,
|
||||
size,
|
||||
context.contentResolver.getType(selectedUri),
|
||||
selectedUri,
|
||||
width,
|
||||
height,
|
||||
orientation,
|
||||
duration
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return videoList
|
||||
}
|
||||
|
||||
private fun createIntent(): Intent {
|
||||
return Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, !single)
|
||||
type = "video/*"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker.entity
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
data class MultiPickerAudioType(
|
||||
override val displayName: String?,
|
||||
override val size: Long,
|
||||
override val mimeType: String?,
|
||||
override val contentUri: Uri,
|
||||
val duration: Long
|
||||
) : MultiPickerBaseType
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker.entity
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
interface MultiPickerBaseType {
|
||||
val displayName: String?
|
||||
val size: Long
|
||||
val mimeType: String?
|
||||
val contentUri: Uri
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker.entity
|
||||
|
||||
data class MultiPickerContactType(
|
||||
val displayName: String,
|
||||
val photoUri: String?,
|
||||
val phoneNumberList: List<String>,
|
||||
val emailList: List<String>
|
||||
) {
|
||||
private val FORMAT_CONTACT = "Name: %s, Photo: %s, Phones: %s, Emails: %s"
|
||||
|
||||
override fun toString(): String {
|
||||
val phoneNumberString = phoneNumberList.joinToString(separator = ", ", prefix = "[", postfix = "]")
|
||||
val emailString = emailList.joinToString(separator = ", ", prefix = "[", postfix = "]")
|
||||
return String.format(FORMAT_CONTACT, displayName, photoUri, phoneNumberString, emailString)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker.entity
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
data class MultiPickerFileType(
|
||||
override val displayName: String?,
|
||||
override val size: Long,
|
||||
override val mimeType: String?,
|
||||
override val contentUri: Uri
|
||||
) : MultiPickerBaseType
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker.entity
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
data class MultiPickerImageType(
|
||||
override val displayName: String?,
|
||||
override val size: Long,
|
||||
override val mimeType: String?,
|
||||
override val contentUri: Uri,
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
val orientation: Int
|
||||
) : MultiPickerBaseType
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker.entity
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
data class MultiPickerVideoType(
|
||||
override val displayName: String?,
|
||||
override val size: Long,
|
||||
override val mimeType: String?,
|
||||
override val contentUri: Uri,
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
val orientation: Int,
|
||||
val duration: Long
|
||||
) : MultiPickerBaseType
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.multipicker
|
||||
|
||||
import junit.framework.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
include ':vector', ':matrix-sdk-android', ':matrix-sdk-android-rx', ':diff-match-patch'
|
||||
include ':multipicker'
|
||||
|
|
|
@ -254,6 +254,7 @@ dependencies {
|
|||
implementation project(":matrix-sdk-android")
|
||||
implementation project(":matrix-sdk-android-rx")
|
||||
implementation project(":diff-match-patch")
|
||||
implementation project(":multipicker")
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<!-- Adding CAMERA permission prevents Chromebooks to see the application on the PlayStore -->
|
||||
<!-- Tell that the Camera is not mandatory to install the application -->
|
||||
|
|
|
@ -156,6 +156,7 @@ import im.vector.riotx.features.reactions.EmojiReactionPickerActivity
|
|||
import im.vector.riotx.features.settings.VectorPreferences
|
||||
import im.vector.riotx.features.share.SharedData
|
||||
import im.vector.riotx.features.themes.ThemeUtils
|
||||
import im.vector.riotx.multipicker.MultiPicker
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
@ -290,9 +291,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
roomDetailViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RoomDetailViewEvents.Failure -> showErrorInSnackbar(it.throwable)
|
||||
is RoomDetailViewEvents.OnNewTimelineEvents -> scrollOnNewMessageCallback.addNewTimelineEventIds(it.eventIds)
|
||||
is RoomDetailViewEvents.ActionSuccess -> displayRoomDetailActionSuccess(it)
|
||||
is RoomDetailViewEvents.Failure -> showErrorInSnackbar(it.throwable)
|
||||
is RoomDetailViewEvents.OnNewTimelineEvents -> scrollOnNewMessageCallback.addNewTimelineEventIds(it.eventIds)
|
||||
is RoomDetailViewEvents.ActionSuccess -> displayRoomDetailActionSuccess(it)
|
||||
is RoomDetailViewEvents.ActionFailure -> displayRoomDetailActionFailure(it)
|
||||
is RoomDetailViewEvents.ShowMessage -> showSnackWithMessage(it.message, Snackbar.LENGTH_LONG)
|
||||
is RoomDetailViewEvents.NavigateToEvent -> navigateToEvent(it)
|
||||
|
@ -516,6 +517,24 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
when (requestCode) {
|
||||
MultiPicker.REQUEST_CODE_PICK_IMAGE -> {
|
||||
MultiPicker.get(MultiPicker.IMAGE).getSelectedFiles(requireContext(), requestCode, resultCode, data)
|
||||
}
|
||||
MultiPicker.REQUEST_CODE_PICK_VIDEO -> {
|
||||
MultiPicker.get(MultiPicker.VIDEO).getSelectedFiles(requireContext(), requestCode, resultCode, data)
|
||||
}
|
||||
MultiPicker.REQUEST_CODE_PICK_FILE -> {
|
||||
MultiPicker.get(MultiPicker.FILE).getSelectedFiles(requireContext(), requestCode, resultCode, data)
|
||||
}
|
||||
MultiPicker.REQUEST_CODE_PICK_AUDIO -> {
|
||||
MultiPicker.get(MultiPicker.AUDIO).getSelectedFiles(requireContext(), requestCode, resultCode, data)
|
||||
}
|
||||
MultiPicker.REQUEST_CODE_PICK_CONTACT -> {
|
||||
MultiPicker.get(MultiPicker.CONTACT).getSelectedFiles(requireContext(), requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
|
||||
val hasBeenHandled = attachmentsHelper.onActivityResult(requestCode, resultCode, data)
|
||||
if (!hasBeenHandled && resultCode == RESULT_OK && data != null) {
|
||||
when (requestCode) {
|
||||
|
@ -1351,10 +1370,10 @@ class RoomDetailFragment @Inject constructor(
|
|||
private fun launchAttachmentProcess(type: AttachmentTypeSelectorView.Type) {
|
||||
when (type) {
|
||||
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera()
|
||||
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile()
|
||||
AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery()
|
||||
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio()
|
||||
AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact()
|
||||
AttachmentTypeSelectorView.Type.FILE -> MultiPicker.get(MultiPicker.FILE).startWith(this)
|
||||
AttachmentTypeSelectorView.Type.GALLERY -> MultiPicker.get(MultiPicker.IMAGE).startWith(this)
|
||||
AttachmentTypeSelectorView.Type.AUDIO -> MultiPicker.get(MultiPicker.AUDIO).startWith(this)
|
||||
AttachmentTypeSelectorView.Type.CONTACT -> MultiPicker.get(MultiPicker.CONTACT).startWith(this)
|
||||
AttachmentTypeSelectorView.Type.STICKER -> vectorBaseActivity.notImplemented("Adding stickers")
|
||||
}.exhaustive
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue