Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development #17

Merged
merged 3 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ android {

buildTypes {
debug {
testCoverageEnabled true
testCoverageEnabled false
}
release {
minifyEnabled false
Expand Down Expand Up @@ -104,11 +104,13 @@ dependencies {
implementation 'com.google.firebase:firebase-crashlytics:18.2.4'
implementation 'com.google.firebase:firebase-analytics:20.0.0'
implementation 'com.google.firebase:firebase-firestore:24.0.0'
implementation 'com.google.firebase:firebase-auth-ktx:21.0.1'

// Photo Loader
implementation 'com.jsibbold:zoomage:1.3.1'
implementation 'com.github.bumptech.glide:glide:4.12.0'
kapt "com.github.bumptech.glide:compiler:4.11.0"
implementation "com.airbnb.android:lottie:$lottie_version"

// Testing
testImplementation 'junit:junit:4.13.2'
Expand Down
29 changes: 29 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,41 @@
<application
android:name=".App"
android:allowBackup="true"
android:extractNativeLibs="true"
android:icon="@drawable/ic_gallery"
android:label="@string/app_name"
android:roundIcon="@drawable/ic_gallery"
android:theme="@style/Theme.InteractivePhotoGallery">

<activity
android:name=".ui.gallery.GalleryActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="rashadtanjim.info"
android:scheme="https" />

<data
android:host="rashadtanjim.info"
android:pathPrefix="/picsum"
android:scheme="https" />

<data
android:host="www.rashadtanjim.info"
android:pathPrefix="/picsum"
android:scheme="https" />
</intent-filter>

</activity>

<activity
android:name=".ui.MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
38 changes: 38 additions & 0 deletions app/src/main/java/info/rashadtanjim/core/utlis/HelperUtils.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package info.rashadtanjim.core.utlis

import android.Manifest
import android.content.ContentValues
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import androidx.core.content.ContextCompat
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream

fun Context.isConnected(): Boolean {
val cm = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
Expand Down Expand Up @@ -63,4 +67,38 @@ fun Context.saveToSdCard(bitmap: Bitmap): String? {
e.printStackTrace()
}
return stored
}

//Make sure to call this function on a worker thread, else it will block main thread
fun Context.saveImageInQ(bitmap: Bitmap): Uri? {
val filename = "PICSUM_PHOTO_${System.currentTimeMillis()}"
var fos: OutputStream? = null
var imageUri: Uri? = null

val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, System.currentTimeMillis().toString())
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { //this one
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
put(MediaStore.MediaColumns.IS_PENDING, 1)
}
}

//use application context to get contentResolver
val contentResolver = this.contentResolver

contentResolver.also { resolver ->
imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
fos = imageUri?.let { resolver.openOutputStream(it) }
}

fos?.use { bitmap.compress(Bitmap.CompressFormat.JPEG, 70, it) }

contentValues.clear()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentValues.put(MediaStore.Video.Media.IS_PENDING, 0)
}
imageUri?.let { contentResolver.update(it, contentValues, null, null) }

return imageUri
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import javax.inject.Inject
class UserPreferences @Inject constructor(
private val context: Context
) {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "photo_store")
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "photo_gallery")

val nightMode: Flow<Boolean?>
get() = context.dataStore.data.map { preferences ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package info.rashadtanjim.interactivephotogallery.ui

import android.animation.Animator
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.core.content.res.ResourcesCompat
import dagger.hilt.android.AndroidEntryPoint
import info.rashadtanjim.interactivephotogallery.R
import info.rashadtanjim.interactivephotogallery.data.UserPreferences
import info.rashadtanjim.interactivephotogallery.databinding.ActivityMainBinding
import info.rashadtanjim.interactivephotogallery.ui.base.BaseActivity
import info.rashadtanjim.interactivephotogallery.ui.gallery.GalleryActivity
import javax.inject.Inject

@AndroidEntryPoint
Expand All @@ -18,10 +23,30 @@ class MainActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
}

binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

window.navigationBarColor =
ResourcesCompat.getColor(resources, R.color.background, null)

binding.lottie.setAnimation(R.raw.gallary_lottie)
binding.lottie.playAnimation()
binding.lottie.addAnimatorListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) {}

override fun onAnimationEnd(animation: Animator) {
startActivity(Intent(this@MainActivity, GalleryActivity::class.java))
finishAffinity()
}

override fun onAnimationCancel(animation: Animator) {}
override fun onAnimationRepeat(animation: Animator) {}
})

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import info.rashadtanjim.interactivephotogallery.data.repository.BaseRepository
import info.rashadtanjim.interactivephotogallery.data.repository.UserRepository
import info.rashadtanjim.interactivephotogallery.ui.SharedViewModel
import info.rashadtanjim.interactivephotogallery.ui.gallery.SharedViewModel

class ViewModelFactory(
private val repository: BaseRepository
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package info.rashadtanjim.interactivephotogallery.ui.fragment
package info.rashadtanjim.interactivephotogallery.ui.gallery

import android.os.Bundle
import android.view.LayoutInflater
Expand All @@ -9,7 +9,6 @@ import info.rashadtanjim.interactivephotogallery.App
import info.rashadtanjim.interactivephotogallery.data.repository.UserRepository
import info.rashadtanjim.interactivephotogallery.data.source.remote.PicsumApi
import info.rashadtanjim.interactivephotogallery.databinding.FragmentAboutAppBinding
import info.rashadtanjim.interactivephotogallery.ui.SharedViewModel
import info.rashadtanjim.interactivephotogallery.ui.base.BaseFragment

class AboutAppFragment :
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package info.rashadtanjim.interactivephotogallery.ui.gallery

import android.os.Bundle
import androidx.core.content.res.ResourcesCompat
import dagger.hilt.android.AndroidEntryPoint
import info.rashadtanjim.interactivephotogallery.R
import info.rashadtanjim.interactivephotogallery.data.UserPreferences
import info.rashadtanjim.interactivephotogallery.databinding.ActivityGalleryBinding
import info.rashadtanjim.interactivephotogallery.ui.base.BaseActivity
import javax.inject.Inject

@AndroidEntryPoint
class GalleryActivity : BaseActivity() {
private lateinit var binding: ActivityGalleryBinding

@Inject
lateinit var userPreferences: UserPreferences

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityGalleryBinding.inflate(layoutInflater)
setContentView(binding.root)

window.navigationBarColor =
ResourcesCompat.getColor(resources, R.color.background, null)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package info.rashadtanjim.interactivephotogallery.ui.fragment
package info.rashadtanjim.interactivephotogallery.ui.gallery

import android.os.Bundle
import android.view.LayoutInflater
Expand All @@ -14,7 +14,6 @@ import info.rashadtanjim.interactivephotogallery.data.source.remote.PicsumApi
import info.rashadtanjim.interactivephotogallery.data.util.DataState
import info.rashadtanjim.interactivephotogallery.databinding.FragmentGalleryBinding
import info.rashadtanjim.interactivephotogallery.domain.model.PicsumPhotosItem
import info.rashadtanjim.interactivephotogallery.ui.SharedViewModel
import info.rashadtanjim.interactivephotogallery.ui.adapter.GalleryAdapter
import info.rashadtanjim.interactivephotogallery.ui.base.BaseFragment

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package info.rashadtanjim.interactivephotogallery.ui.fragment
package info.rashadtanjim.interactivephotogallery.ui.gallery

import android.Manifest
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toBitmap
Expand All @@ -19,7 +20,6 @@ import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.gms.tasks.Task
import com.google.firebase.dynamiclinks.DynamicLink.*
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks
Expand Down Expand Up @@ -103,41 +103,79 @@ class PhotoViewFragment : DialogFragment() {
/**
* Event: The action listen will trigger devices' default sharing option to share photo
* The Task will be done using firebase's [FirebaseDynamicLinks]
* Before sharing [hasStoragePermission] checks write permission
*/

binding.imageButtonShare.setOnClickListener {

FirebaseDynamicLinks.getInstance()
.createDynamicLink()
.setLink(Uri.parse("https://interactivephotogallery.page.link/picsum/$selectedPhoto"))
.setDomainUriPrefix("https://rashadtanjim.info")
.setAndroidParameters(
AndroidParameters.Builder("info.rashadtanjim.interactivephotogallery")
.setMinimumVersion(1)
.build()
)
.setSocialMetaTagParameters(
SocialMetaTagParameters.Builder()
.setTitle("https://interactivephotogallery.page.link/picsum")
.setDescription(getString(R.string.about_app))
.setTitle(getString(R.string.app_name))
.build()
)
.buildShortDynamicLink()
.addOnCompleteListener { task: Task<ShortDynamicLink> ->
if (task.isSuccessful) {
val shortLink = task.result.shortLink
val intent = Intent()
intent.action = Intent.ACTION_SEND
intent.putExtra(Intent.EXTRA_STREAM, shortLink)
intent.type = "image/*"
val shareIntent = Intent.createChooser(intent, "Share Photo!")
startActivity(shareIntent, null)
} else {
showToast(getString(R.string.something_went_wrong))
}
val mBitmap = binding.zoomViewPhoto.drawable.toBitmap()

if (requireContext().hasStoragePermission()) {

val uri: Uri? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
requireContext().saveImageInQ(mBitmap)
} else {
val path = MediaStore.Images.Media.insertImage(
requireActivity().contentResolver, mBitmap,
"Image Description", null
)
Uri.parse(path)
}

FirebaseDynamicLinks.getInstance()
.createDynamicLink()
.setLink(Uri.parse("https://rashadtanjim.info/picsum/$selectedPhoto"))
.setDomainUriPrefix("https://rashadtanjim.info")
.setAndroidParameters(
AndroidParameters.Builder("info.rashadtanjim.interactivephotogallery")
.setMinimumVersion(0)
.build()
)
.setIosParameters(
IosParameters.Builder("info.rashadtanjim.interactivephotogallery")
.setAppStoreId("0000000000")
.setMinimumVersion("0.0.1")
.build()
)
.setGoogleAnalyticsParameters(
GoogleAnalyticsParameters.Builder()
.setSource("picsum")
.setMedium("social")
.setCampaign("picsum-images")
.build()
)
.setSocialMetaTagParameters(
SocialMetaTagParameters.Builder()
.setTitle("rashadtanjim.info")
.setDescription(getString(R.string.about_app))
.setTitle(getString(R.string.app_name))
.build()
)
.buildShortDynamicLink()
.addOnCompleteListener { task: Task<ShortDynamicLink> ->
if (task.isSuccessful) {
val shortLink = task.result.shortLink

val intent = Intent()
intent.action = Intent.ACTION_SEND

intent.putExtra(Intent.EXTRA_TEXT, "&$shortLink")
intent.putExtra(Intent.EXTRA_STREAM, uri)

// intent.setDataAndType(uri, "image/*")
intent.type = "image/*"
val shareIntent = Intent.createChooser(intent, "Share Photo!")
startActivity(shareIntent, null)
} else {
showToast(getString(R.string.something_went_wrong))
}
}
} else {
ActivityCompat.requestPermissions(
requireActivity(), arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
PERMISSION_REQUEST_CODE
)
}
}
}

Expand Down
Loading