Skip to content

Commit b5266ac

Browse files
authored
Merge pull request #15 from arindamxd/development
Jetpack Compose Support
2 parents db4c884 + c70de56 commit b5266ac

32 files changed

+1583
-580
lines changed

app/build.gradle

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,27 @@ android {
5151
resValue "string", "app_version", "${defaultConfig.versionName} (build ${defaultConfig.versionCode}.release)"
5252
resValue "string", "app_name", "CameraX"
5353

54-
minifyEnabled false
54+
minifyEnabled true
5555
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
5656
}
5757
}
5858

59+
buildFeatures {
60+
viewBinding true
61+
compose true
62+
}
63+
5964
compileOptions {
60-
sourceCompatibility JavaVersion.VERSION_17
61-
targetCompatibility JavaVersion.VERSION_17
65+
sourceCompatibility JavaVersion.VERSION_1_9
66+
targetCompatibility JavaVersion.VERSION_1_9
6267
}
6368

6469
kotlinOptions {
65-
jvmTarget = JavaVersion.VERSION_17
70+
jvmTarget = JavaVersion.VERSION_1_9
6671
}
6772

68-
buildFeatures {
69-
viewBinding true
73+
composeOptions {
74+
kotlinCompilerExtensionVersion = "1.5.3"
7075
}
7176

7277
// Set the source of tests to same for both Unit and Instrumented tests
@@ -81,11 +86,11 @@ android {
8186
}*/
8287

8388
// Necessary for Robolectric (Unit tests)
84-
testOptions {
89+
/*testOptions {
8590
unitTests {
8691
includeAndroidResources = true
8792
}
88-
}
93+
}*/
8994
}
9095

9196
dependencies {
@@ -119,7 +124,7 @@ dependencies {
119124
implementation "androidx.exifinterface:exifinterface:1.3.6"
120125

121126
// Coil
122-
implementation "io.coil-kt:coil:2.4.0"
127+
implementation "io.coil-kt:coil-compose:2.4.0"
123128

124129
// Material Design
125130
implementation "com.google.android.material:material:1.9.0"
@@ -129,11 +134,46 @@ dependencies {
129134

130135
// Firebase SDK
131136
implementation "com.google.firebase:firebase-analytics-ktx:21.3.0"
132-
implementation "com.google.firebase:firebase-crashlytics:18.4.1"
137+
implementation "com.google.firebase:firebase-crashlytics:18.4.3"
133138

134139
// [CONFLICT FIX] Guava
135140
api "com.google.guava:guava:28.1-android"
136141

142+
def composeBom = platform('androidx.compose:compose-bom:2023.08.00')
143+
implementation composeBom
144+
androidTestImplementation composeBom
145+
146+
// Material Design 3
147+
implementation 'androidx.compose.material3:material3'
148+
149+
// Android Studio Preview support
150+
implementation 'androidx.compose.ui:ui-tooling-preview'
151+
debugImplementation 'androidx.compose.ui:ui-tooling'
152+
153+
// UI Tests
154+
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
155+
debugImplementation 'androidx.compose.ui:ui-test-manifest'
156+
157+
// Optional - Included automatically by material, only add when you need
158+
// the icons but not the material library (e.g. when using Material3 or a
159+
// custom design system based on Foundation)
160+
implementation 'androidx.compose.material:material-icons-core'
161+
// Optional - Add full set of material icons
162+
implementation 'androidx.compose.material:material-icons-extended'
163+
// Optional - Add window size utils
164+
implementation 'androidx.compose.material3:material3-window-size-class'
165+
166+
// Optional - Integration with activities
167+
implementation 'androidx.activity:activity-compose:1.7.2'
168+
// Optional - Integration with ViewModels
169+
//implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'
170+
// Optional - Integration with LiveData
171+
//implementation 'androidx.compose.runtime:runtime-livedata'
172+
// Optional - Integration with RxJava
173+
//implementation 'androidx.compose.runtime:runtime-rxjava2'
174+
175+
implementation "androidx.paging:paging-compose:3.2.1"
176+
137177
// Unit testing
138178
testImplementation "androidx.test.ext:junit:1.1.5"
139179
testImplementation "androidx.test:rules:1.5.0"

app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
<!-- Declare permissions -->
1313
<uses-permission android:name="android.permission.INTERNET" />
1414
<uses-permission android:name="android.permission.CAMERA" />
15-
<!--<uses-permission android:name="android.permission.RECORD_AUDIO" />
16-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />-->
15+
<!--<uses-permission android:name="android.permission.RECORD_AUDIO" />-->
16+
<!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />-->
1717

1818
<application
1919
android:name=".CameraX"
@@ -93,9 +93,7 @@
9393
android:name=".ui.settings.SettingsActivity"
9494
android:rotationAnimation="seamless"
9595
android:screenOrientation="fullUser"
96-
tools:targetApi="o">
97-
98-
</activity>
96+
tools:targetApi="o" />
9997

10098
</application>
10199

app/src/main/java/com/arindam/camerax/ui/base/BaseFragment.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import java.util.*
2222
* Created by Arindam Karmakar on 17/04/20.
2323
*/
2424

25+
@Deprecated("Please use BaseFragmentCompose", ReplaceWith("BaseFragmentCompose()"))
2526
abstract class BaseFragment<T : ViewBinding> : Fragment() {
2627

2728
protected lateinit var binding: T
@@ -34,6 +35,7 @@ abstract class BaseFragment<T : ViewBinding> : Fragment() {
3435
return if (it == null) provideView()
3536
else {
3637
binding = it
38+
setComposeView()
3739
binding.root
3840
}
3941
}
@@ -46,6 +48,8 @@ abstract class BaseFragment<T : ViewBinding> : Fragment() {
4648
open fun provideBinding(): T? = null
4749
open fun provideView(): View? = View(context)
4850

51+
abstract fun setComposeView()
52+
4953
abstract fun setupView(view: View, savedInstanceState: Bundle?)
5054

5155
protected fun navigate(directions: NavDirections) = findNavController().navigate(directions)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.arindam.camerax.ui.base
2+
3+
import android.content.pm.PackageManager
4+
import android.os.Bundle
5+
import android.view.LayoutInflater
6+
import android.view.View
7+
import android.view.ViewGroup
8+
import androidx.annotation.StringRes
9+
import androidx.compose.ui.platform.ComposeView
10+
import androidx.core.content.ContextCompat
11+
import androidx.fragment.app.Fragment
12+
import androidx.navigation.NavDirections
13+
import androidx.navigation.fragment.findNavController
14+
import com.arindam.camerax.R
15+
import com.arindam.camerax.util.commons.Constants.PERMISSIONS.REQUIRED_PERMISSIONS
16+
import com.arindam.camerax.util.display.Toaster
17+
import java.io.File
18+
import java.text.SimpleDateFormat
19+
import java.util.*
20+
21+
/**
22+
* Created by Arindam Karmakar on 17/04/20.
23+
*/
24+
25+
abstract class BaseFragmentCompose : Fragment() {
26+
27+
override fun onCreateView(
28+
inflater: LayoutInflater,
29+
container: ViewGroup?,
30+
savedInstanceState: Bundle?
31+
): View = ComposeView(inflater.context).apply {
32+
layoutParams = ViewGroup.LayoutParams(
33+
ViewGroup.LayoutParams.MATCH_PARENT,
34+
ViewGroup.LayoutParams.MATCH_PARENT
35+
)
36+
setComposeView(this)
37+
}
38+
39+
abstract fun setComposeView(view: ComposeView)
40+
41+
protected fun navigate(directions: NavDirections) = findNavController().navigate(directions)
42+
protected fun navigateBack() = findNavController().navigateUp()
43+
44+
/** Convenience method used to check if all permissions required by this app are granted */
45+
protected fun hasPermissions() = REQUIRED_PERMISSIONS.all {
46+
ContextCompat.checkSelfPermission(requireContext(), it) == PackageManager.PERMISSION_GRANTED
47+
}
48+
49+
/** Use external media if it is available, our app's file directory otherwise */
50+
protected fun getOutputFileDirectory(): File {
51+
val appContext = requireContext().applicationContext
52+
val mediaDir = requireContext().externalMediaDirs.firstOrNull()?.let {
53+
File(it, appContext.resources.getString(R.string.app_name)).apply { mkdirs() }
54+
}
55+
return if (mediaDir != null && mediaDir.exists()) mediaDir else appContext.filesDir
56+
}
57+
58+
protected fun isDirectoryNotEmpty(): Boolean = getOutputFileDirectory().listFiles()?.isNotEmpty() == true
59+
60+
/** Helper function used to create a timestamped file */
61+
protected fun createFile(baseFolder: File, format: String, extension: String) = File(
62+
baseFolder, SimpleDateFormat(format, Locale.US).format(System.currentTimeMillis()) + extension
63+
)
64+
65+
protected fun createFileName(format: String): String {
66+
return SimpleDateFormat(format, Locale.US).format(System.currentTimeMillis())
67+
}
68+
69+
protected fun showToast(@StringRes resId: Int) {
70+
showToast(requireContext().getString(resId))
71+
}
72+
73+
protected fun showToast(message: String) {
74+
Toaster.show(requireContext(), message)
75+
}
76+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.arindam.camerax.ui.compose
2+
3+
import android.content.res.Configuration
4+
import androidx.compose.ui.tooling.preview.Preview
5+
6+
/**
7+
* Created by Arindam Karmakar on 13/09/23.
8+
*/
9+
10+
@Preview(
11+
name = "Small Font",
12+
group = "Font Scales",
13+
fontScale = 0.5f
14+
)
15+
@Preview(
16+
name = "Large Font",
17+
group = "Font Scales",
18+
fontScale = 1.5f
19+
)
20+
annotation class FontScalePreviews
21+
22+
@Preview(
23+
name = "Dark Mode",
24+
group = "UI Mode",
25+
uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL,
26+
showBackground = true,
27+
showSystemUi = true
28+
)
29+
@Preview(
30+
name = "Light Mode",
31+
group = "UI Mode",
32+
uiMode = Configuration.UI_MODE_NIGHT_NO or Configuration.UI_MODE_TYPE_NORMAL,
33+
showBackground = true,
34+
showSystemUi = true
35+
)
36+
annotation class DarkLightPreviews

0 commit comments

Comments
 (0)