diff --git a/app/build.gradle b/app/build.gradle
index 8bc9144..f03f785 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -12,12 +12,12 @@ android {
keyPassword '123456'
}
}
- compileSdkVersion 29
- buildToolsVersion "29.0.0"
+ compileSdkVersion 30
+ buildToolsVersion "30.0.1"
defaultConfig {
applicationId "com.opensooq.supernova.gligarexample"
minSdkVersion 17
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -33,8 +33,11 @@ android {
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.1.0'
+ implementation "androidx.activity:activity-ktx:1.2.0-beta01"
+ implementation 'com.google.android.material:material:1.2.1'
+ implementation "androidx.fragment:fragment-ktx:1.3.0-beta01"
+ implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- implementation project(':gligar')
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation project(":gligar")
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6fe7740..c54d45a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,14 +9,20 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
-
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/opensooq/supernova/gligarexample/ActivityResultLauncher.kt b/app/src/main/java/com/opensooq/supernova/gligarexample/ActivityResultLauncher.kt
new file mode 100644
index 0000000..3044ff9
--- /dev/null
+++ b/app/src/main/java/com/opensooq/supernova/gligarexample/ActivityResultLauncher.kt
@@ -0,0 +1,34 @@
+package com.opensooq.supernova.gligarexample
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import com.opensooq.supernova.gligar.GligarPicker
+import com.opensooq.supernova.gligar.ui.GligarScreenResult
+import kotlinx.android.synthetic.main.activity_main.*
+
+class ActivityResultLauncher : AppCompatActivity() {
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ val startForResult = registerForActivityResult(object : GligarScreenResult() {
+ override fun getGligarIntentLauncher(): Intent {
+ return GligarPicker()
+ .singleSelection(true)
+ .disableCamera(false).cameraDirect(false).requestCode(PICKER_REQUEST_CODE)
+ .withActivity(this@ActivityResultLauncher).show()
+ }
+ }) {
+ if (!it.isNullOrEmpty()) {
+ imagesCount.text = "Number of selected Images: ${it.size}"
+ }
+ }
+
+ startForResult.launch(0)
+ }
+
+
+}
diff --git a/app/src/main/java/com/opensooq/supernova/gligarexample/ActivityStarterLauncherV2.kt b/app/src/main/java/com/opensooq/supernova/gligarexample/ActivityStarterLauncherV2.kt
new file mode 100644
index 0000000..5717dd2
--- /dev/null
+++ b/app/src/main/java/com/opensooq/supernova/gligarexample/ActivityStarterLauncherV2.kt
@@ -0,0 +1,42 @@
+package com.opensooq.supernova.gligarexample
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import com.opensooq.supernova.gligar.ui.GligarResultBuilder
+import kotlinx.android.synthetic.main.activity_main.*
+
+class ActivityStarterLauncherV2 : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ val starter = registerForActivityResult(object : GligarResultBuilder(this@ActivityStarterLauncherV2) {
+ override fun build(activity: FragmentActivity?, fragment: Fragment?, input: List?): Intent {
+ this addLimitImages 20
+ this addRequestCode REQUEST_CODE
+ this disableCamera true
+ this isCustomExtSuported arrayListOf("png", "jpg", "jpeg")
+ this cameraDirect false
+ this isSingleSelection false
+ this isPreItemsSelected input
+ return getFinalIntent()
+ }
+ }) {
+ if (!it.isNullOrEmpty()) {
+ imagesCount.text = "Number of selected Images: ${it.size}"
+ }
+ }
+
+ starter.launch(arrayListOf(
+ "/storage/emulated/0/DCIM/Screenshots/Screenshot_20201129-101300_Facebook.jpg",
+ "/storage/emulated/0/DCIM/Screenshots/Screenshot_20201129-093307_Chrome.jpg",
+ "/storage/emulated/0/DCIM/Screenshots/Screenshot_20201129-071900_Facebook.jpg",
+ "/storage/emulated/0/DCIM/Screenshots/Screenshot_20201129-071500_Facebook.jpg"
+ ))
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/opensooq/supernova/gligarexample/CustomToolbarScreen.kt b/app/src/main/java/com/opensooq/supernova/gligarexample/CustomToolbarScreen.kt
new file mode 100644
index 0000000..cc3c73f
--- /dev/null
+++ b/app/src/main/java/com/opensooq/supernova/gligarexample/CustomToolbarScreen.kt
@@ -0,0 +1,49 @@
+package com.opensooq.supernova.gligarexample
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.view.MenuItem
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.opensooq.supernova.gligar.GligarPicker
+import com.opensooq.supernova.gligar.ui.GligarPickerFragment
+import com.opensooq.supernova.gligar.ui.GligarPickerListener
+import kotlinx.android.synthetic.main.activity_main_custom.*
+
+class CustomToolbarScreen : AppCompatActivity(), GligarPickerListener {
+
+ @SuppressLint("RestrictedApi")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main_custom)
+ custom_toolbar?.let {
+ setSupportActionBar(it)
+ supportActionBar?.setDisplayShowTitleEnabled(true)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ supportActionBar?.setDefaultDisplayHomeAsUpEnabled(true)
+ }
+
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.fragment_container, GligarPickerFragment.getInstance(getGligarPicker()))
+ .commitNowAllowingStateLoss()
+ }
+
+ private fun getGligarPicker(): GligarPicker {
+ return GligarPicker()
+ .cameraDirect(false)
+ .disableCamera(true)
+ .limit(20)
+ .setCustomBackgroundColor("#FFA07A")
+ .supportExtensions(arrayListOf("png", "jpg", "jpeg"))
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ onBackPressed()
+ return super.onOptionsItemSelected(item)
+ }
+
+ override fun onImagesSelected(items: Array) {
+ Toast.makeText(this, "Selected Images : ${items.size}", Toast.LENGTH_SHORT).show()
+ }
+
+}
diff --git a/app/src/main/java/com/opensooq/supernova/gligarexample/MainScreenLauncher.kt b/app/src/main/java/com/opensooq/supernova/gligarexample/MainScreenLauncher.kt
new file mode 100644
index 0000000..7a1bd71
--- /dev/null
+++ b/app/src/main/java/com/opensooq/supernova/gligarexample/MainScreenLauncher.kt
@@ -0,0 +1,34 @@
+package com.opensooq.supernova.gligarexample
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import kotlinx.android.synthetic.main.activity_main_launcher.*
+
+class MainScreenLauncher : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main_launcher)
+
+ normal_launcher_button?.setOnClickListener {
+ startActivity(Intent(this@MainScreenLauncher, NormalActivityStarter::class.java))
+ }
+
+ start_launcher_button?.setOnClickListener {
+ startActivity(Intent(this@MainScreenLauncher, ActivityResultLauncher::class.java))
+ }
+
+ supported_files_button?.setOnClickListener {
+ startActivity(Intent(this@MainScreenLauncher, SupportedFilesLauncher::class.java))
+ }
+
+ pre_selected_files_button?.setOnClickListener {
+ startActivity(Intent(this@MainScreenLauncher, ActivityStarterLauncherV2::class.java))
+ }
+
+ custom_screen?.setOnClickListener {
+ startActivity(Intent(this@MainScreenLauncher, CustomToolbarScreen::class.java))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/opensooq/supernova/gligarexample/MainActivity.kt b/app/src/main/java/com/opensooq/supernova/gligarexample/NormalActivityStarter.kt
similarity index 95%
rename from app/src/main/java/com/opensooq/supernova/gligarexample/MainActivity.kt
rename to app/src/main/java/com/opensooq/supernova/gligarexample/NormalActivityStarter.kt
index 04d4233..ee0bfbe 100644
--- a/app/src/main/java/com/opensooq/supernova/gligarexample/MainActivity.kt
+++ b/app/src/main/java/com/opensooq/supernova/gligarexample/NormalActivityStarter.kt
@@ -7,7 +7,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.opensooq.supernova.gligar.GligarPicker
import kotlinx.android.synthetic.main.activity_main.*
-class MainActivity : AppCompatActivity() {
+class NormalActivityStarter : AppCompatActivity() {
val PICKER_REQUEST_CODE = 30
diff --git a/app/src/main/java/com/opensooq/supernova/gligarexample/SupportedFilesLauncher.kt b/app/src/main/java/com/opensooq/supernova/gligarexample/SupportedFilesLauncher.kt
new file mode 100644
index 0000000..f298314
--- /dev/null
+++ b/app/src/main/java/com/opensooq/supernova/gligarexample/SupportedFilesLauncher.kt
@@ -0,0 +1,32 @@
+package com.opensooq.supernova.gligarexample
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import com.opensooq.supernova.gligar.GligarPicker
+import com.opensooq.supernova.gligar.ui.GligarScreenResult
+import kotlinx.android.synthetic.main.activity_main.*
+
+class SupportedFilesLauncher : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ val startForResult = registerForActivityResult(object : GligarScreenResult() {
+ override fun getGligarIntentLauncher(): Intent {
+ return GligarPicker()
+ .supportExtensions(arrayListOf("png"))
+ .singleSelection(true)
+ .disableCamera(false).cameraDirect(false).requestCode(PICKER_REQUEST_CODE)
+ .withActivity(this@SupportedFilesLauncher).show()
+ }
+ }) {
+ if (!it.isNullOrEmpty()) {
+ imagesCount.text = "Number of selected Images: ${it.size}"
+ }
+ }
+
+ startForResult.launch(0)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 68363d7..da97492 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".MainActivity">
+ tools:context=".ActivityResultLauncher">
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main_launcher.xml b/app/src/main/res/layout/activity_main_launcher.xml
new file mode 100644
index 0000000..3fb2b45
--- /dev/null
+++ b/app/src/main/res/layout/activity_main_launcher.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 5885930..2ccced9 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -8,4 +8,9 @@
- @color/colorAccent
+
+
diff --git a/build.gradle b/build.gradle
index a328da5..c50a7c0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,33 +1,77 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = '1.3.50'
+ ext.kotlin_version = '1.4.31'
repositories {
google()
- jcenter()
-
+ maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath 'com.android.tools.build:gradle:4.0.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.0'
- classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
-
-
-
+ classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.21.0"
}
}
allprojects {
+ apply plugin: "com.jfrog.artifactory"
+ apply plugin: 'maven-publish'
+
repositories {
google()
- jcenter()
-
+ maven { url "${artifactory_contextUrl}/gligar-gradle-dev-local" }
+ maven { url "https://plugins.gradle.org/m2/" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
+
+ext {
+ packageName = "com.opensooq.supernova"
+ artifactId = "gligar"
+ libraryVersion = "1.1.1"
+
+ deploymentEnvironment = 'dev'
+
+ repoKey = "gligar-gradle-${deploymentEnvironment}-local"
+ resolverRepoKey = "gligar-gradle-${deploymentEnvironment}"
+}
+
+publishing {
+ publications {
+ aar(MavenPublication) {
+ groupId rootProject.ext.packageName
+ version = rootProject.ext.libraryVersion
+ artifactId rootProject.ext.artifactId
+ artifact("$projectDir/gligar/build/outputs/aar/gligar-release.aar")
+ }
+ }
+}
+
+artifactory {
+ contextUrl = "${artifactory_contextUrl}"
+ publish {
+ repository {
+ repoKey = rootProject.ext.repoKey
+ username = "${artifactory_user}"
+ password = "${artifactory_password}"
+ maven = true
+ }
+ defaults {
+ publications('aar')
+ publishArtifacts = true
+ publishPom = true
+ }
+ }
+ resolve {
+ repository {
+ repoKey = rootProject.ext.resolverRepoKey
+ username = "${artifactory_user}"
+ password = "${artifactory_password}"
+ maven = true
+
+ }
+ }
+}
diff --git a/gligar/build.gradle b/gligar/build.gradle
index d2df5ad..707a24a 100644
--- a/gligar/build.gradle
+++ b/gligar/build.gradle
@@ -1,34 +1,8 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
-apply plugin: 'com.jfrog.bintray'
-apply plugin: 'com.github.dcendents.android-maven'
-
-ext {
- bintrayRepo = 'Gligar'
- bintrayName = 'gligar' // Has to be same as your library module name
-
- publishedGroupId = 'com.opensooq.supernova'
- libraryName = 'gligar'
- artifact = 'gligar' // Has to be same as your library module name
-
- libraryDescription = 'Image Picker for Android, Pick an image from Gallery or Capture a new image with Camera'
-
- // Your github repo link
- siteUrl = 'https://github.com/OpenSooq/GligarPicker'
- gitUrl = 'https://github.com/OpenSooq/GligarPicker.git'
- githubRepository= 'OpenSooq/GligarPicker'
-
- libraryVersion = '1.1.0'
-
- developerId = 'OpenSooq'
- developerName = 'OpenSooq'
- developerEmail = 'hani.momanii@gmail.com'
-
- licenseName = 'The Apache Software License, Version 2.0'
- licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
- allLicenses = ["Apache-2.0"]
-}
+apply plugin: "com.jfrog.artifactory"
+apply plugin: 'maven-publish'
android {
compileSdkVersion 29
@@ -61,8 +35,10 @@ android {
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.1.0'
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation "androidx.activity:activity-ktx:1.2.0-beta01"
+ implementation "androidx.fragment:fragment-ktx:1.3.0-beta01"
+ implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha04'
implementation "androidx.lifecycle:lifecycle-runtime:2.1.0-alpha04"
@@ -73,15 +49,9 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0'
implementation "android.arch.paging:runtime:1.0.1"
- implementation 'com.github.bumptech.glide:glide:4.9.0'
- annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
+ implementation 'com.github.bumptech.glide:glide:4.11.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
implementation 'com.google.android.material:material:1.2.0-alpha02'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
}
-
-apply from: 'https://raw.githubusercontent.com/nisrulz/JCenter/master/installv1.gradle'
-apply from: 'https://gist.githubusercontent.com/tamtom/f54a538637178e4818bbc72f24a73e2d/raw/af6f8b6782475230cfff852ae11669c936e739a2/bintrayv1.gradle'
-tasks.withType(Javadoc).all {
- enabled = false
-}
\ No newline at end of file
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/GligarPicker.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/GligarPicker.kt
index 038d2a7..31950e1 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/GligarPicker.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/GligarPicker.kt
@@ -2,11 +2,19 @@ package com.opensooq.supernova.gligar
import android.app.Activity
import android.content.Intent
+import android.os.Bundle
import androidx.fragment.app.Fragment
+import com.opensooq.supernova.gligar.ui.GligarResultBuilder
+import com.opensooq.supernova.gligar.ui.ImagePickerActivity
import com.opensooq.supernova.gligar.ui.ImagePickerActivity.Companion.EXTRA_CAMERA_DIRECT
+import com.opensooq.supernova.gligar.ui.ImagePickerActivity.Companion.EXTRA_CUSTOM_COLOR
import com.opensooq.supernova.gligar.ui.ImagePickerActivity.Companion.EXTRA_DISABLE_CAMERA
import com.opensooq.supernova.gligar.ui.ImagePickerActivity.Companion.EXTRA_LIMIT
+import com.opensooq.supernova.gligar.ui.ImagePickerActivity.Companion.EXTRA_SINGLE_SELECTION
+import com.opensooq.supernova.gligar.ui.ImagePickerActivity.Companion.EXTRA_SUPPRTED_TYPES
import com.opensooq.supernova.gligar.ui.ImagePickerActivity.Companion.startActivityForResult
+import com.opensooq.supernova.gligar.utils.ALL_TYPES
+import com.opensooq.supernova.gligar.utils.getSupportedImagesExt
import java.lang.IllegalStateException
/**
@@ -26,17 +34,51 @@ class GligarPicker {
private var limit: Int = 10
private var disableCamera: Boolean = false
private var cameraDirect: Boolean = false
+ private var isSingleSelection: Boolean = false
+ private var supportedExt: ArrayList = arrayListOf()
+ private var isPreSelectedItemsAttached: Boolean = false
+ private var items: List? = null
+ private var customBackgroundColor: String? = null
fun requestCode(requestCode: Int) = apply { this.requestCode = requestCode }
fun limit(limit: Int) = apply { this.limit = limit }
fun disableCamera(disableCamera: Boolean) = apply { this.disableCamera = disableCamera }
+ fun singleSelection(isSingleSelection: Boolean) = apply { this.isSingleSelection = isSingleSelection }
fun cameraDirect(cameraDirect: Boolean) = apply { this.cameraDirect = cameraDirect }
fun withActivity(activity: Activity) = apply { this.withActivity = activity }
fun withFragment(fragment: Fragment) = apply { this.withFragment = fragment }
+ fun supportExtensions(supportedExt: ArrayList) = apply { this.supportedExt = supportedExt }
+ fun isPreItemsSelected(items: List?) = apply {
+ this.isPreSelectedItemsAttached = true
+ this.items = items
+ }
+
+ fun setCustomBackgroundColor(color: String) = apply {
+ this.customBackgroundColor = color
+ }
+
+ fun getBuildBundle(): Bundle {
+ val args = Bundle()
+ args.putInt(EXTRA_LIMIT, limit)
+ args.putBoolean(EXTRA_CAMERA_DIRECT, cameraDirect)
+ args.putBoolean(EXTRA_SINGLE_SELECTION, isSingleSelection)
+ args.putString(EXTRA_SUPPRTED_TYPES, getSupportedImagesExt(supportedExt))
+ args.putString(EXTRA_CUSTOM_COLOR, customBackgroundColor)
+ if (!cameraDirect) {
+ args.putBoolean(EXTRA_DISABLE_CAMERA, disableCamera)
+ }
+ if (isPreSelectedItemsAttached) {
+ items?.let {
+ args.putBoolean(ImagePickerActivity.EXTRA_PRE_SELECTED, isPreSelectedItemsAttached)
+ args.putStringArray(ImagePickerActivity.EXTRA_PRE_SELECTED_ITEMS, it.toTypedArray())
+ }
+ }
+ return args
+ }
- fun show() {
+ fun show(): Intent {
if(withActivity == null && withFragment ==null){
throw IllegalStateException("Activity or fragment should be passed, use withActivity(activity) or withFragment(fragment) to set any.")
}
@@ -44,15 +86,25 @@ class GligarPicker {
val intent = Intent()
intent.putExtra(EXTRA_LIMIT, limit)
intent.putExtra(EXTRA_CAMERA_DIRECT, cameraDirect)
+ intent.putExtra(EXTRA_SINGLE_SELECTION, isSingleSelection)
+ intent.putExtra(EXTRA_SUPPRTED_TYPES, getSupportedImagesExt(supportedExt))
if (!cameraDirect) {
intent.putExtra(EXTRA_DISABLE_CAMERA, disableCamera)
}
+ if (isPreSelectedItemsAttached) {
+ items?.let {
+ intent.putExtra(ImagePickerActivity.EXTRA_PRE_SELECTED, isPreSelectedItemsAttached)
+ intent.putExtra(ImagePickerActivity.EXTRA_PRE_SELECTED_ITEMS, it.toTypedArray())
+ }
+ }
+
if(withActivity!=null){
startActivityForResult(withActivity!!,requestCode,intent)
}else{
startActivityForResult(withFragment!!,requestCode,intent)
}
+ return intent
}
}
\ No newline at end of file
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/adapters/ImagesAdapter.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/adapters/ImagesAdapter.kt
index 2028c3b..ce92a80 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/adapters/ImagesAdapter.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/adapters/ImagesAdapter.kt
@@ -35,9 +35,9 @@ internal class ImagesAdapter(var clickListener: ItemClickListener) :
}
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
- holder.itemView.setOnClickListener { clickListener.onItemClicked(position) }
val data = images[position]
+ holder.itemView.setOnClickListener { clickListener.onItemClicked(position, data.source) }
if (data.source== ImageSource.GALLERY) {
holder.imgView.visibility = View.VISIBLE
holder.captureView.visibility = View.GONE
@@ -55,6 +55,12 @@ internal class ImagesAdapter(var clickListener: ItemClickListener) :
}
Glide.with(holder.img).load(data.imagePath)
.transition(DrawableTransitionOptions().crossFade()).into(holder.img)
+
+ if (data.isCustomPositionActivated()) {
+ data.selectedPosition?.let {
+ holder.selectionNum.text = it.toString()
+ }
+ }
return
}
if (data.source== ImageSource.CAMERA) {
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/adapters/ItemClickListener.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/adapters/ItemClickListener.kt
index 6069d5d..aca3488 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/adapters/ItemClickListener.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/adapters/ItemClickListener.kt
@@ -1,9 +1,11 @@
package com.opensooq.supernova.gligar.adapters
+import com.opensooq.OpenSooq.ui.imagePicker.model.ImageSource
+
/**
* Created by Hani AlMomani on 28,November,2019
*/
internal interface ItemClickListener {
- fun onItemClicked(position : Int)
+ fun onItemClicked(position : Int, source: ImageSource)
}
\ No newline at end of file
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/ImagesDataSource.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/ImagesDataSource.kt
index 1e2334a..530d40b 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/ImagesDataSource.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/ImagesDataSource.kt
@@ -2,7 +2,10 @@ package com.opensooq.supernova.gligar.dataSource
import android.content.ContentResolver
import android.database.Cursor
+import android.os.Build
+import android.os.Bundle
import android.provider.MediaStore
+import androidx.annotation.RequiresApi
import androidx.paging.PositionalDataSource
import com.opensooq.OpenSooq.ui.imagePicker.model.AlbumItem
import com.opensooq.OpenSooq.ui.imagePicker.model.ImageItem
@@ -22,6 +25,9 @@ import kotlin.coroutines.CoroutineContext
internal class ImagesDataSource(private val contentResolver: ContentResolver){
+ internal var selectedPosition = 0
+ internal var isSelected = false
+
fun loadAlbums(): ArrayList {
val albumCursor = contentResolver.query(
cursorUri,
@@ -52,47 +58,96 @@ internal class ImagesDataSource(private val contentResolver: ContentResolver){
return list
}
+ private fun getCurserQuery(albumItem: AlbumItem?, offset: Int): Cursor? {
+ try {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val queryBundle = Bundle().apply {
+ putInt(ContentResolver.QUERY_ARG_LIMIT, PAGE_SIZE)
+ putInt(ContentResolver.QUERY_ARG_OFFSET, offset)
+ putString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER, ORDER_BY)
+ }
+
+ if (!(albumItem == null || albumItem.isAll)) {
+ queryBundle.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, "${MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME} =?")
+ queryBundle.putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(albumItem.name))
+ }
+
+ return contentResolver.query(
+ cursorUri,
+ getSelectionProjection(),
+ queryBundle,
+ null
+ )
+ } else {
+ return if (albumItem == null || albumItem.isAll) {
+ contentResolver.query(cursorUri, getSelectionProjection(), null, null, ORDER_BY + " LIMIT $PAGE_SIZE" + " OFFSET $offset")
+ } else {
+ contentResolver.query(cursorUri, getSelectionProjection(), "${MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME} =?", arrayOf(albumItem.name), ORDER_BY + " LIMIT $PAGE_SIZE" + " OFFSET $offset")
+ }
+ }
+ } catch (ex: Exception) {
+ return null
+ }
+ }
+
+ private fun getSelectionProjection(): Array {
+ return arrayOf(ID_COLUMN, PATH_COLUMN)
+ }
+
fun loadAlbumImages(
albumItem: AlbumItem?,
- page: Int
+ page: Int,
+ supportedImages: String? = null,
+ preSelectedImages: Array? = null
): ArrayList {
- val offset = page * PAGE_SIZE
- val list: ArrayList = arrayListOf()
var photoCursor: Cursor? = null
+ val list: ArrayList = ArrayList()
try {
- if (albumItem == null || albumItem.isAll) {
- photoCursor = contentResolver.query(
- cursorUri,
- arrayOf(
- ID_COLUMN,
- PATH_COLUMN
- ),
- null,
- null,
- "$ORDER_BY LIMIT $PAGE_SIZE OFFSET $offset"
- )
- } else {
- photoCursor = contentResolver.query(
- cursorUri,
- arrayOf(
- ID_COLUMN,
- PATH_COLUMN
- ),
- "${MediaStore.Images.ImageColumns.BUCKET_ID} =?",
- arrayOf(albumItem.bucketId),
- "$ORDER_BY LIMIT $PAGE_SIZE OFFSET $offset"
- )
+ val offset = page * PAGE_SIZE
+ photoCursor = getCurserQuery(albumItem, offset)
+
+ photoCursor?.isAfterLast
+ if (photoCursor == null) {
+ return list
}
- photoCursor?.isAfterLast ?: return list
- photoCursor.doWhile {
+
+ while(photoCursor.moveToNext()) {
val image = photoCursor.getString((photoCursor.getColumnIndex(PATH_COLUMN)))
- list.add(ImageItem(image, ImageSource.GALLERY, 0))
+ if (supportedImages != null) {
+ val imageType = image.substring(image.lastIndexOf(".") + 1)
+ if (supportedImages.contains(imageType)) {
+ if (preSelectedImages == null) {
+ list.add(ImageItem(image, ImageSource.GALLERY, ImageItem.NOT_SELECTED))
+ } else {
+ addSelectedImageToList(preSelectedImages, image, list)
+ }
+ }
+ } else {
+ if (preSelectedImages == null) {
+ list.add(ImageItem(image, ImageSource.GALLERY, ImageItem.NOT_SELECTED))
+ } else {
+ addSelectedImageToList(preSelectedImages, image, list)
+ }
+ }
}
} finally {
- if (photoCursor != null && !photoCursor.isClosed()) {
+ if (photoCursor != null && !photoCursor.isClosed) {
photoCursor.close()
}
}
return list
}
+
+ private fun addSelectedImageToList(preSelectedImages: Array, image: String, list: ArrayList) {
+ if (preSelectedImages.contains(image)) {
+ isSelected = true
+ }
+
+ if (isSelected) {
+ selectedPosition += 1
+ }
+ list.add(ImageItem(image, ImageSource.GALLERY, if (isSelected) ImageItem.SELECTED else ImageItem.NOT_SELECTED, selectedPosition))
+ isSelected = false
+ }
+
}
\ No newline at end of file
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/model/ImageItem.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/model/ImageItem.kt
index 52589ce..5850907 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/model/ImageItem.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/model/ImageItem.kt
@@ -8,4 +8,20 @@ import kotlinx.android.parcel.Parcelize
*/
@Parcelize
-internal data class ImageItem(var imagePath: String, var source: ImageSource, var selected: Int) : Parcelable
+internal data class ImageItem(
+ var imagePath: String,
+ var source: ImageSource,
+ var selected: Int,
+ var selectedPosition: Int? = null
+) : Parcelable {
+
+ companion object {
+ const val SELECTED = 1
+ const val NOT_SELECTED = 0
+ }
+
+ fun isCustomPositionActivated(): Boolean {
+ return selected == SELECTED
+ }
+
+}
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/model/ImageSource.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/model/ImageSource.kt
index 44f0a4d..702e3e0 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/model/ImageSource.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/dataSource/model/ImageSource.kt
@@ -4,7 +4,7 @@ package com.opensooq.OpenSooq.ui.imagePicker.model
* Created by Hani AlMomani on 23,April,2019
*/
-internal enum class ImageSource(val source: Int) {
+enum class ImageSource(val source: Int) {
GALLERY(1),
CAMERA(2),
DUM(3)
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarPickerFragment.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarPickerFragment.kt
new file mode 100644
index 0000000..a4fcd77
--- /dev/null
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarPickerFragment.kt
@@ -0,0 +1,428 @@
+package com.opensooq.supernova.gligar.ui
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Color
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.provider.MediaStore
+import android.provider.Settings
+import android.text.TextUtils
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ImageView
+import androidx.appcompat.app.AppCompatDelegate
+import androidx.appcompat.widget.AppCompatSpinner
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import androidx.core.content.FileProvider
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.Observer
+import androidx.lifecycle.SavedStateViewModelFactory
+import androidx.lifecycle.ViewModelProvider
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.button.MaterialButton
+import com.google.android.material.snackbar.Snackbar
+import com.opensooq.OpenSooq.ui.imagePicker.model.AlbumItem
+import com.opensooq.OpenSooq.ui.imagePicker.model.ImageItem
+import com.opensooq.OpenSooq.ui.imagePicker.model.ImageSource
+import com.opensooq.supernova.gligar.GligarPicker
+import com.opensooq.supernova.gligar.R
+import com.opensooq.supernova.gligar.adapters.AlbumsAdapter
+import com.opensooq.supernova.gligar.adapters.ImagesAdapter
+import com.opensooq.supernova.gligar.adapters.ItemClickListener
+import com.opensooq.supernova.gligar.adapters.LoadMoreListener
+import com.opensooq.supernova.gligar.utils.PAGE_SIZE
+import com.opensooq.supernova.gligar.utils.createTempImageFile
+import kotlinx.android.synthetic.main.activity_image_picker_gligar.*
+import kotlinx.android.synthetic.main.include_permssion_alert_gligar.*
+import java.io.File
+import java.lang.IllegalArgumentException
+
+class GligarPickerFragment : Fragment(), LoadMoreListener.OnLoadMoreListener, ItemClickListener {
+
+
+ private lateinit var mainViewModel: PickerViewModel
+ private var mAlbumAdapter: AlbumsAdapter? = null
+ private var mImagesAdapter: ImagesAdapter? = null
+ private var loadMoreListener: LoadMoreListener? = null
+ private var isPermissionGranted = false
+ private var isSaveState = false
+ private var forceCamera = false
+
+ private lateinit var icDone: ImageView
+ private lateinit var alertBtn: MaterialButton
+ private lateinit var alert: View
+ private lateinit var albumsSpinner: AppCompatSpinner
+ private lateinit var rvImages: RecyclerView
+ private lateinit var changeAlbum: View
+ private lateinit var rootView: View
+ private var listener: GligarPickerListener? = null
+
+ init {
+ AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
+ }
+
+ companion object {
+ fun getInstance(picker: GligarPicker): GligarPickerFragment {
+ val fragment = GligarPickerFragment()
+ fragment.arguments = picker.getBuildBundle()
+ return fragment
+ }
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.activity_image_picker_gligar, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ activity?.let {
+ mainViewModel = ViewModelProvider(it, SavedStateViewModelFactory(it.application, this)).get(
+ PickerViewModel::class.java
+ )
+
+ initFragmentOperations(savedInstanceState, it)
+ }
+ }
+
+ private fun initFragmentOperations(savedInstanceState: Bundle?, activity: FragmentActivity) {
+ icDone = _ic_done
+ alertBtn = _alert_btn
+ alert = _v_alert
+ albumsSpinner = _albums_spinner
+ rvImages = _rv_images
+ changeAlbum = _change_album
+ rootView = _v_rootView
+
+ mainViewModel.init(activity.contentResolver)
+ if (savedInstanceState != null) {
+ isSaveState = true
+ mainViewModel.loadSaveState()
+ } else {
+ arguments?.let {
+ it.getString(ImagePickerActivity.EXTRA_CUSTOM_COLOR, "")?.let {
+ if (!TextUtils.isEmpty(it)) {
+ try {
+ pickerToolbar?.setBackgroundColor(Color.parseColor(it))
+ } catch (ex: Exception) {
+ println(ex.message)
+ ex.printStackTrace()
+ }
+ }
+ }
+ mainViewModel.bindArguments(it)
+ }
+ }
+ setImagesAdapter()
+ icDone.setOnClickListener { sendResults() }
+ }
+
+
+ private fun checkCameraPermission() {
+ if (mainViewModel.isOverLimit()) {
+ showLimitMsg()
+ return
+ }
+
+ if (Build.VERSION.SDK_INT >= 23) {
+ if (checkPermission(android.Manifest.permission.CAMERA)) {
+ cameraPermissionGranted()
+ } else {
+ requestPermission(
+ arrayOf(android.Manifest.permission.CAMERA),
+ ImagePickerActivity.CAMERA_PERMISSION_REQUEST_CODE
+ )
+ }
+ } else {
+ cameraPermissionGranted()
+ }
+ }
+
+ private fun checkStoragePermission() {
+ if (Build.VERSION.SDK_INT >= 23) {
+ if (checkPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
+ storagePermissionGranted()
+ } else {
+ requestPermission(
+ arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
+ ImagePickerActivity.STORAGE_PERMISSION_REQUEST_CODE
+ );
+ }
+ } else {
+ storagePermissionGranted()
+ }
+ }
+
+
+ private fun openCamera() = checkCameraPermission()
+
+ private fun loadAlbums() {
+ isPermissionGranted = true
+ mainViewModel.loadAlbums()
+ }
+
+ private fun storagePermissionGranted() {
+ hideAlert()
+ loadAlbums()
+ }
+
+ private fun cameraPermissionGranted() {
+ hideAlert()
+ try {
+ val photoFile: File? = createTempImageFile(requireActivity())
+ mainViewModel.mCurrentPhotoPath = photoFile?.absolutePath
+ val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
+ val myPhotoFileUri = activity?.let {
+ FileProvider.getUriForFile(it,
+ activity?.applicationContext?.packageName + ".provider",
+ photoFile!!
+ )
+ }
+ cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, myPhotoFileUri)
+ cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ startActivityForResult(
+ Intent.createChooser(cameraIntent, ""),
+ ImagePickerActivity.REQUEST_CODE_CAMERA_IMAGE
+ )
+ } catch (e: Exception) {
+ Log.e("Picker", e.message, e)
+ }
+ }
+
+ private fun checkPermission(permission: String): Boolean {
+ val result = ContextCompat.checkSelfPermission(requireActivity(), permission)
+ return result == PackageManager.PERMISSION_GRANTED
+ }
+
+ private fun requestPermission(permissions: Array, requestCode: Int) {
+ if (ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), permissions[0])) {
+ showAlert()
+ } else {
+ ActivityCompat.requestPermissions(requireActivity(), permissions, requestCode);
+ }
+ }
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ try {
+ listener = context as GligarPickerListener
+ } catch (ex: Exception) {
+ throw IllegalArgumentException("Your Activity Should Implement GligarPickerListener")
+ }
+ }
+
+ override fun onDetach() {
+ listener = null
+ super.onDetach()
+ }
+
+ private fun showAlert() {
+ alertBtn.setOnClickListener { showAppPage() }
+ alert.visibility = View.VISIBLE
+ }
+
+ private fun hideAlert() {
+ alert.visibility = View.GONE
+ }
+
+ private fun setAlbumsAdapter(albums: List) {
+ mAlbumAdapter = AlbumsAdapter(albums, requireActivity().applicationContext)
+ albumsSpinner.adapter = mAlbumAdapter
+ albumsSpinner.setSelection(mainViewModel.mCurrentSelectedAlbum, false)
+ albumsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onNothingSelected(parent: AdapterView<*>?) {
+
+ }
+
+ override fun onItemSelected(
+ adapterView: AdapterView<*>,
+ view: View,
+ pos: Int,
+ l: Long
+ ) {
+ mainViewModel.onAlbumChanged(mAlbumAdapter?.getItem(pos), pos)
+ mImagesAdapter?.images?.clear()
+ mImagesAdapter?.notifyDataSetChanged()
+ }
+ }
+ changeAlbum.setOnClickListener { albumsSpinner.performClick() }
+ }
+
+ private fun setImagesAdapter() {
+ mImagesAdapter = ImagesAdapter(this)
+ val mLayoutManager = GridLayoutManager(requireActivity(), 3)
+ rvImages.layoutManager = mLayoutManager
+ rvImages.setHasFixedSize(true)
+ mImagesAdapter?.images = arrayListOf()
+ mImagesAdapter?.images?.addAll(if (isSaveState && !mainViewModel.saveStateImages.isNullOrEmpty()) mainViewModel.saveStateImages else mainViewModel.dumpImagesList)
+ mainViewModel.saveStateImages.clear()
+ rvImages.adapter = mImagesAdapter
+ observe()
+ setLoadMoreListener()
+ }
+
+ override fun onItemClicked(position: Int, source: ImageSource) {
+ if (source == ImageSource.CAMERA) {
+ openCamera()
+ } else {
+ mainViewModel.setImageSelection(position, mImagesAdapter?.images)
+ }
+ }
+
+ private fun observe() {
+
+ mainViewModel.mDirectCamera.observe(viewLifecycleOwner, Observer {
+ forceCamera = it
+ })
+ mainViewModel.mAlbums.observe(viewLifecycleOwner, Observer {
+ setAlbumsAdapter(it)
+ })
+ mainViewModel.mLastAddedImages.observe(viewLifecycleOwner, Observer {
+ addImages(it)
+ })
+ mainViewModel.mNotifyPosition.observe(viewLifecycleOwner, Observer {
+ mImagesAdapter?.notifyItemChanged(it)
+ })
+
+ mainViewModel.mNotifyInsert.observe(viewLifecycleOwner, Observer {
+ mImagesAdapter?.notifyDataSetChanged()
+ })
+
+ mainViewModel.mDoneEnabled.observe(viewLifecycleOwner, Observer {
+ setDoneVisibilty(it)
+ })
+
+ mainViewModel.showOverLimit.observe(viewLifecycleOwner, Observer {
+ showLimitMsg()
+ })
+ }
+
+ private fun addImages(it: ArrayList) {
+ loadMoreListener?.setFinished(false)
+ if (it.isNullOrEmpty()) {
+ loadMoreListener?.setFinished()
+ loadMoreListener?.setLoaded()
+ return
+ }
+ val isFirstPage = mainViewModel.mPage == 0
+ isPermissionGranted = true
+ if (it.size < PAGE_SIZE) {
+ loadMoreListener?.setFinished()
+ }
+
+ var lastPos = mImagesAdapter?.images?.size ?: 0
+ if (isFirstPage) {
+ mImagesAdapter?.images = it
+ mImagesAdapter?.notifyDataSetChanged()
+ } else {
+ mImagesAdapter?.images?.addAll(it)
+ mImagesAdapter?.notifyItemRangeInserted(lastPos, it.size)
+ }
+ loadMoreListener?.setLoaded()
+ if (forceCamera) {
+ openCamera()
+ forceCamera = false
+ }
+ }
+
+ private fun setDoneVisibilty(visible: Boolean) {
+ icDone.visibility = if (visible) View.VISIBLE else View.GONE
+ }
+
+ private fun setLoadMoreListener() {
+ if (loadMoreListener != null) {
+ rvImages.removeOnScrollListener(loadMoreListener!!)
+ }
+ loadMoreListener = LoadMoreListener(rvImages.layoutManager as GridLayoutManager)
+ loadMoreListener?.setOnLoadMoreListener(this@GligarPickerFragment)
+ rvImages.addOnScrollListener(loadMoreListener!!)
+ }
+
+ override fun onLoadMore() {
+ if (!isPermissionGranted) {
+ return
+ }
+ mainViewModel.loadMoreImages()
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (resultCode == Activity.RESULT_OK) {
+ when (requestCode) {
+ ImagePickerActivity.REQUEST_CODE_CAMERA_IMAGE -> {
+ mainViewModel.addCameraItem(mImagesAdapter?.images)
+ setDoneVisibilty(true)
+ }
+ }
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ when (requestCode) {
+ ImagePickerActivity.STORAGE_PERMISSION_REQUEST_CODE -> {
+ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ storagePermissionGranted()
+ } else {
+ showAlert()
+ }
+ return
+ }
+ ImagePickerActivity.CAMERA_PERMISSION_REQUEST_CODE -> {
+ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ cameraPermissionGranted()
+ } else {
+ showAlert()
+ }
+ return
+ }
+ }
+ }
+
+ private fun sendResults() {
+ listener?.onImagesSelected(mainViewModel.getSelectedPaths())
+ activity?.onBackPressed()
+ }
+
+ private fun showLimitMsg() {
+ Snackbar.make(rootView, R.string.over_limit_msg, Snackbar.LENGTH_LONG).show()
+ }
+
+
+ private fun showAppPage() {
+ val intent = Intent(
+ Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Uri.fromParts("package", requireActivity().packageName, null)
+ )
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ startActivity(intent)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ checkStoragePermission()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ if (::mainViewModel.isInitialized) {
+ mainViewModel.saveStateImages = mImagesAdapter?.images ?: arrayListOf()
+ mainViewModel.saveState()
+ }
+ super.onSaveInstanceState(outState)
+ }
+
+
+}
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarPickerListener.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarPickerListener.kt
new file mode 100644
index 0000000..4fd5d65
--- /dev/null
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarPickerListener.kt
@@ -0,0 +1,7 @@
+package com.opensooq.supernova.gligar.ui
+
+interface GligarPickerListener {
+
+ fun onImagesSelected(items: Array)
+
+}
\ No newline at end of file
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarResultBuilder.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarResultBuilder.kt
new file mode 100644
index 0000000..d22c606
--- /dev/null
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarResultBuilder.kt
@@ -0,0 +1,102 @@
+package com.opensooq.supernova.gligar.ui
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import androidx.activity.result.contract.ActivityResultContract
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import com.opensooq.supernova.gligar.GligarPicker
+import com.opensooq.supernova.gligar.utils.getSupportedImagesExt
+
+abstract class GligarResultBuilder constructor(
+ private val activity: FragmentActivity? = null,
+ private val fragment: Fragment? = null
+) : ActivityResultContract?, Array?>() {
+
+ private var limit: Int = 10
+ private var disableCamera: Boolean = false
+ private var cameraDirect: Boolean = false
+ private var isSingleSelection: Boolean = false
+ private var supportedExt: ArrayList = arrayListOf()
+ private var isPreSelectedItemsAttached: Boolean = false
+ private var requestCode: Int = REQUEST_CODE
+ private var items: List? = null
+ companion object {
+ const val REQUEST_CODE = 234
+ }
+
+ override fun createIntent(context: Context, input: List?): Intent {
+ if (activity == null && fragment == null) {
+ throw IllegalArgumentException("Gligar Should has Activity or Fragment to Start")
+ }
+ return build(activity, fragment, input)
+ }
+
+ override fun parseResult(resultCode: Int, intent: Intent?): Array? {
+ return when (resultCode) {
+ Activity.RESULT_OK -> intent?.extras?.getStringArray(GligarPicker.IMAGES_RESULT)
+ else -> null
+ }
+ }
+
+ fun getFinalIntent(): Intent {
+ val intent = Intent()
+ intent.putExtra(ImagePickerActivity.EXTRA_LIMIT, limit)
+ intent.putExtra(ImagePickerActivity.EXTRA_CAMERA_DIRECT, cameraDirect)
+ intent.putExtra(ImagePickerActivity.EXTRA_SINGLE_SELECTION, isSingleSelection)
+ intent.putExtra(ImagePickerActivity.EXTRA_SUPPRTED_TYPES, getSupportedImagesExt(supportedExt))
+ if (!cameraDirect) {
+ intent.putExtra(ImagePickerActivity.EXTRA_DISABLE_CAMERA, disableCamera)
+ }
+
+ if (isPreSelectedItemsAttached) {
+ items?.let {
+ intent.putExtra(ImagePickerActivity.EXTRA_PRE_SELECTED, isPreSelectedItemsAttached)
+ intent.putExtra(ImagePickerActivity.EXTRA_PRE_SELECTED_ITEMS, it.toTypedArray())
+ }
+ }
+
+ if (activity != null) {
+ ImagePickerActivity.startActivityForResult(activity, requestCode, intent)
+ } else {
+ fragment?.let {
+ ImagePickerActivity.startActivityForResult(it, requestCode, intent)
+ }
+ }
+
+ return intent
+ }
+
+ infix fun addRequestCode(requestCode: Int) {
+ this.requestCode = requestCode
+ }
+
+ infix fun isPreItemsSelected(items: List?) {
+ this.isPreSelectedItemsAttached = true
+ this.items = items
+ }
+
+ infix fun isCustomExtSuported(supportedExt: ArrayList) {
+ this.supportedExt = supportedExt
+ }
+
+ infix fun isSingleSelection(isSingleSelection: Boolean) {
+ this.isSingleSelection = isSingleSelection
+ }
+
+ infix fun cameraDirect(cameraDirect: Boolean) {
+ this.cameraDirect = cameraDirect
+ }
+
+ infix fun disableCamera(disableCamera: Boolean) {
+ this.disableCamera = disableCamera
+ }
+
+ infix fun addLimitImages(limit: Int) {
+ this.limit = limit
+ }
+
+ abstract fun build(activity: FragmentActivity?, fragment: Fragment?, input: List?): Intent
+
+}
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarScreenResult.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarScreenResult.kt
new file mode 100644
index 0000000..45f77d4
--- /dev/null
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/GligarScreenResult.kt
@@ -0,0 +1,29 @@
+package com.opensooq.supernova.gligar.ui
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import androidx.activity.result.contract.ActivityResultContract
+import androidx.fragment.app.FragmentActivity
+import com.opensooq.supernova.gligar.GligarPicker
+
+abstract class GligarScreenResult : ActivityResultContract?>() {
+
+ companion object {
+ val PICKER_REQUEST_CODE = 30
+ }
+
+ override fun createIntent(context: Context, input: Any?): Intent {
+ return getGligarIntentLauncher()
+ }
+
+ override fun parseResult(resultCode: Int, intent: Intent?): Array? {
+ return when (resultCode) {
+ Activity.RESULT_OK -> intent?.extras?.getStringArray(GligarPicker.IMAGES_RESULT)
+ else -> null
+ }
+ }
+
+ abstract fun getGligarIntentLauncher(): Intent
+
+}
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/ui/ImagePickerActivity.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/ImagePickerActivity.kt
index a18f5a8..823af11 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/ui/ImagePickerActivity.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/ImagePickerActivity.kt
@@ -29,6 +29,7 @@ import com.google.android.material.button.MaterialButton
import com.google.android.material.snackbar.Snackbar
import com.opensooq.OpenSooq.ui.imagePicker.model.AlbumItem
import com.opensooq.OpenSooq.ui.imagePicker.model.ImageItem
+import com.opensooq.OpenSooq.ui.imagePicker.model.ImageSource
import com.opensooq.supernova.gligar.GligarPicker.Companion.IMAGES_RESULT
import com.opensooq.supernova.gligar.R
import com.opensooq.supernova.gligar.adapters.AlbumsAdapter
@@ -55,10 +56,15 @@ internal class ImagePickerActivity : AppCompatActivity(), LoadMoreListener.OnLoa
companion object {
const val EXTRA_LIMIT = "limit"
const val EXTRA_CAMERA_DIRECT = "camera_direct"
+ const val EXTRA_SINGLE_SELECTION = "single_selection"
+ const val EXTRA_SUPPRTED_TYPES = "supported_types"
+ const val EXTRA_CUSTOM_COLOR = "custom_color"
+ const val EXTRA_PRE_SELECTED = "pre_selected_key"
+ const val EXTRA_PRE_SELECTED_ITEMS = "pre_selected"
const val EXTRA_DISABLE_CAMERA = "disable_camera"
const val STORAGE_PERMISSION_REQUEST_CODE = 100
const val CAMERA_PERMISSION_REQUEST_CODE = 101
- private const val REQUEST_CODE_CAMERA_IMAGE = 102
+ const val REQUEST_CODE_CAMERA_IMAGE = 102
fun startActivityForResult(
fragment: Fragment,
@@ -251,12 +257,11 @@ internal class ImagePickerActivity : AppCompatActivity(), LoadMoreListener.OnLoa
setLoadMoreListener()
}
- override fun onItemClicked(position: Int) {
- when (position) {
- 0 -> openCamera()
- else -> {
- mainViewModel.setImageSelection(position, mImagesAdapter?.images)
- }
+ override fun onItemClicked(position: Int, source: ImageSource) {
+ if (source == ImageSource.CAMERA) {
+ openCamera()
+ } else {
+ mainViewModel.setImageSelection(position, mImagesAdapter?.images)
}
}
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/ui/PickerViewModel.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/PickerViewModel.kt
index 4b4d0bf..f86a7c9 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/ui/PickerViewModel.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/ui/PickerViewModel.kt
@@ -2,6 +2,7 @@ package com.opensooq.supernova.gligar.ui
import android.content.ContentResolver
import android.os.Bundle
+import android.text.TextUtils
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
@@ -46,10 +47,14 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
private var mSelectedList = hashMapOf()
private var mCurrentSelection: Int = 0
private var mLimit = 0
+ private var isSingleSelectionEnabled = false
private var mCameraCisabled: Boolean = true
+ private var supportedImages: String = ALL_TYPES
+ private var preSelectedImages: Array? = null
private lateinit var mImageDataSource: ImagesDataSource
private lateinit var contentResolver: ContentResolver
+
private fun getCurrentSelection() = mCurrentSelection
internal fun isOverLimit() = mCurrentSelection >= mLimit
@@ -61,9 +66,13 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
mLimit = extras.getInt(EXTRA_LIMIT, 0)
mCameraCisabled = extras.getBoolean(ImagePickerActivity.EXTRA_DISABLE_CAMERA, false)
mDirectCamera.value = extras.getBoolean(ImagePickerActivity.EXTRA_CAMERA_DIRECT, false)
+ isSingleSelectionEnabled = extras.getBoolean(ImagePickerActivity.EXTRA_SINGLE_SELECTION, false)
+ supportedImages = extras.getString(ImagePickerActivity.EXTRA_SUPPRTED_TYPES, ALL_TYPES)
+ if (extras.getBoolean(ImagePickerActivity.EXTRA_PRE_SELECTED, false)) {
+ this.preSelectedImages = extras.getStringArray(ImagePickerActivity.EXTRA_PRE_SELECTED_ITEMS)
+ }
}
-
internal fun loadAlbums() {
if (!mAlbums.value.isNullOrEmpty()) {
return
@@ -88,17 +97,36 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
}
viewModelScope.launch() {
val images = getImages()
+ mCurrentSelection = mImageDataSource.selectedPosition
+ addSelectedImages(images)
+ if (mCurrentSelection > 0) {
+ mDoneEnabled.postValue(true)
+ }
if (!isLoadMore && !mCameraCisabled) {
- images.add(0, ImageItem("", ImageSource.CAMERA, 0))
+ images.add(0, ImageItem("", ImageSource.CAMERA, ImageItem.NOT_SELECTED))
}
mLastAddedImages.value = images
}
}
- private suspend fun getImages() = withContext(Dispatchers.Default) {
- mImageDataSource.loadAlbumImages(mSelectedAlbum, mPage)
+ private fun addSelectedImages(images: ArrayList) {
+ if (preSelectedImages != null) {
+ mSelectedList.clear()
+ images.forEach {
+ mSelectedList[it.imagePath] = it
+ }
+ }
}
+ private suspend fun getImages(): ArrayList {
+ return withContext(Dispatchers.IO) {
+ if (!TextUtils.equals(supportedImages, ALL_TYPES)) {
+ mImageDataSource.loadAlbumImages(mSelectedAlbum, mPage, supportedImages, preSelectedImages)
+ } else {
+ mImageDataSource.loadAlbumImages(mSelectedAlbum, mPage, null, preSelectedImages)
+ }
+ }
+ }
private suspend fun getAlbums() = withContext(Dispatchers.Default) {
mImageDataSource.loadAlbums()
@@ -108,8 +136,15 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
if (mCurrentPhotoPath.isNullOrEmpty()) {
return
}
- val imageItem =
- ImageItem(mCurrentPhotoPath!!, ImageSource.GALLERY, getCurrentSelectionCountForCamera())
+ val imageItem = ImageItem(mCurrentPhotoPath!!, ImageSource.GALLERY, getCurrentSelectionCountForCamera())
+ if (isSingleSelectionEnabled) {
+ if (mSelectedList.size > 0) {
+ imageItem.selected = 0
+ } else {
+ imageItem.selected = 1
+ }
+ }
+
mSelectedList[imageItem.imagePath] = imageItem
adapterItems?.add(1, imageItem)
mNotifyInsert.value = 1
@@ -117,6 +152,10 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
internal fun setImageSelection(position: Int, adapterImageItem: ArrayList?) {
+ if (isSingleSelectionEnabled) {
+ mSelectedList.clear()
+ }
+
if (adapterImageItem.isNullOrEmpty()) {
return
}
@@ -131,7 +170,11 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
showOverLimit.value = true
return
}
- mCurrentSelection++
+ if (isSingleSelectionEnabled) {
+ mCurrentSelection = 1
+ } else {
+ mCurrentSelection++
+ }
imageItem.selected = mCurrentSelection
mSelectedList[imageItem.imagePath] = imageItem
} else {
@@ -147,11 +190,25 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
}
mNotifyPosition.value = position
mDoneEnabled.value = getCurrentSelection() > 0
- }
+ if (isSingleSelectionEnabled) {
+ for ((i, mItem) in adapterImageItem.withIndex()) {
+ if (!mItem.imagePath.equals(imageItem.imagePath)) {
+ if (mItem.selected > 0) {
+ mItem.selected = 0
+ mNotifyPosition.value = i
+ }
+ }
+ }
+ }
+ }
private fun getCurrentSelectionCountForCamera(): Int {
- mCurrentSelection++
+ if (isSingleSelectionEnabled) {
+ mCurrentSelection = 1
+ } else {
+ mCurrentSelection++
+ }
return mCurrentSelection
}
@@ -167,7 +224,7 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
private fun getDumItems(): ArrayList {
val list = arrayListOf()
- for (x in 0..PAGE_SIZE) list.add(ImageItem("", ImageSource.DUM, 0))
+ for (x in 0..PAGE_SIZE) list.add(ImageItem("", ImageSource.DUM, ImageItem.NOT_SELECTED))
return list
}
@@ -188,7 +245,7 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
savedStateHandle.set(SELECTED_ALBUM, mSelectedAlbum)
savedStateHandle.set(SELECTED_IMAGES, mSelectedList)
savedStateHandle.set(CURRENT_SELECTION, mCurrentSelection)
- savedStateHandle.set(LIMIT, mLimit)
+ savedStateHandle.set(LIMIT_NUMBER, mLimit)
savedStateHandle.set(DISABLE_CAMERA, mCameraCisabled)
}
@@ -197,13 +254,32 @@ internal class PickerViewModel(private val savedStateHandle: SavedStateHandle) :
saveStateImages = savedStateHandle.get(IMAGES) ?: arrayListOf()
mAlbums.value = savedStateHandle.get(ALBUMS) ?: arrayListOf()
mCurrentPhotoPath = savedStateHandle.get(PHOTO_PATH)
- mCurrentSelectedAlbum = savedStateHandle.get(ALBUM_POS) ?: 0
- mPage = savedStateHandle.get(PAGE) ?: 0
mSelectedAlbum = savedStateHandle.get(SELECTED_ALBUM)
mSelectedList = savedStateHandle.get(SELECTED_IMAGES) ?: hashMapOf()
- mCurrentSelection = savedStateHandle.get(CURRENT_SELECTION) ?: 0
- mLimit = savedStateHandle.get(LIMIT) ?: 0
mCameraCisabled = savedStateHandle.get(DISABLE_CAMERA) ?: false
+ mPage = try {
+ savedStateHandle.get(PAGE) ?: 0
+ } catch (ex: Exception) {
+ 0
+ }
+
+ mCurrentSelection = try {
+ savedStateHandle.get(CURRENT_SELECTION) ?: 0
+ } catch (ex: Exception) {
+ 0
+ }
+
+ mLimit = try {
+ savedStateHandle.get(LIMIT_NUMBER) ?: 0
+ } catch (ex: Exception) {
+ 0
+ }
+
+ mCurrentSelectedAlbum = try {
+ savedStateHandle.get(ALBUM_POS) ?: 0
+ } catch (ex: Exception) {
+ 0
+ }
}
}
\ No newline at end of file
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/utils/Consts.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/utils/Consts.kt
index 6987cd0..a19c1c7 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/utils/Consts.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/utils/Consts.kt
@@ -22,5 +22,6 @@ internal const val PAGE = "page"
internal const val SELECTED_ALBUM = "selected_album"
internal const val SELECTED_IMAGES = "selected_images"
internal const val CURRENT_SELECTION = "curren_selection"
-internal const val LIMIT = "limit"
+internal const val LIMIT_NUMBER = "limit"
internal const val DISABLE_CAMERA = "limit"
+internal const val ALL_TYPES = "all"
diff --git a/gligar/src/main/java/com/opensooq/supernova/gligar/utils/Ext.kt b/gligar/src/main/java/com/opensooq/supernova/gligar/utils/Ext.kt
index aa7b76e..548ddf3 100644
--- a/gligar/src/main/java/com/opensooq/supernova/gligar/utils/Ext.kt
+++ b/gligar/src/main/java/com/opensooq/supernova/gligar/utils/Ext.kt
@@ -29,6 +29,18 @@ internal fun Cursor.doWhile(action: () -> Unit) {
}
}
+internal fun getSupportedImagesExt(supportedExt: List): String {
+ var result = ""
+ return if (supportedExt.isEmpty()) {
+ result = ALL_TYPES
+ result
+ } else {
+ supportedExt.forEach {
+ result += "$it/"
+ }
+ result
+ }
+}
@Throws(IOException::class)
internal fun createTempImageFile(context : Context): File {
diff --git a/gligar/src/main/res/xml/file_paths.xml b/gligar/src/main/res/xml/file_paths.xml
index e97913b..445e7ae 100644
--- a/gligar/src/main/res/xml/file_paths.xml
+++ b/gligar/src/main/res/xml/file_paths.xml
@@ -47,6 +47,10 @@
name="my_images"
path="Android/data/com.companyname.yourproject/files/Pictures/" />
+
+
@@ -63,4 +67,5 @@
+
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 23339e0..930abd9 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -19,3 +19,7 @@ android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
+
+artifactory_user=
+artifactory_password=
+artifactory_contextUrl=https://yazan98.jfrog.io/artifactory
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 94f145f..b337ae4 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sat Sep 28 13:43:42 EEST 2019
+#Wed Apr 28 14:29:40 EEST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip