Skip to content

Commit

Permalink
Implement JetPack Compose
Browse files Browse the repository at this point in the history
This commit reimplements the UI with JetPack Compose.
  • Loading branch information
hameno committed Jul 4, 2021
1 parent 442f44f commit ec250b8
Show file tree
Hide file tree
Showing 85 changed files with 3,187 additions and 1,237 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
language: android
jdk:
- openjdk11
android:
components:
- tools
Expand Down
44 changes: 39 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: "androidx.navigation.safeargs.kotlin"
apply plugin: "androidx.navigation.safeargs"
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
apply plugin: 'com.google.firebase.firebase-perf'
apply plugin: 'com.github.triplet.play'
apply plugin: 'com.dicedmelon.gradle.jacoco-android'

android {
compileSdkVersion Config.compile_sdk
Expand All @@ -28,10 +28,15 @@ android {
// Version info
buildConfigField 'String', 'GIT_SHA', "\"${project.ext.gitHash}\""

vectorDrawables {
useSupportLibrary true
}

javaCompileOptions.annotationProcessorOptions.arguments['room.schemaLocation'] = rootProject.file('schemas').toString()
}
buildFeatures {
viewBinding true
compose true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand All @@ -45,8 +50,12 @@ android {
"-Xopt-in=kotlin.ExperimentalStdlibApi",
"-Xopt-in=kotlin.time.ExperimentalTime",
"-Xopt-in=kotlinx.coroutines.FlowPreview",
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-Xopt-in=androidx.compose.foundation.ExperimentalFoundationApi",
"-Xopt-in=androidx.compose.animation.ExperimentalAnimationApi",
"-Xopt-in=androidx.compose.material.ExperimentalMaterialApi"
]
useIR = true
}
testOptions {
unitTests {
Expand Down Expand Up @@ -105,6 +114,9 @@ android {
exclude '**/NOTICE.txt'
exclude '**/*.gwt.xml'
}
composeOptions {
kotlinCompilerExtensionVersion Versions.androidXCompose
}
}

dependencies {
Expand Down Expand Up @@ -133,20 +145,38 @@ dependencies {
implementation Libs.androidx_browser
implementation Libs.androidx_constraint_layout
implementation Libs.androidx_core
implementation "androidx.core:core-splashscreen:1.0.0-alpha01"
implementation Libs.androidx_fragment
implementation Libs.androidx_hilt_work
implementation Libs.androidx_lifecycle_viewmodel
implementation Libs.androidx_lifecycle_livedata
implementation Libs.androidx_lifecycle_java8
implementation Libs.androidx_lifecycle_runtime
implementation Libs.androidx_lifecycle_process
implementation Libs.androidx_navigation_fragment
implementation Libs.androidx_navigation_ui
implementation "androidx.navigation:navigation-compose:$Versions.androidXNavigation"
implementation Libs.androidx_preference
implementation Libs.androidx_recyclerview
implementation Libs.androidx_recyclerview_selection
implementation Libs.androidx_room_runtime
implementation Libs.androidx_room_ktx
implementation Libs.androidx_work_runtime
implementation Libs.androidx_work_gcm
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.activity:activity-compose:1.3.0-rc01'
implementation "androidx.compose.ui:ui:$Versions.androidXCompose"
implementation "androidx.compose.foundation:foundation:$Versions.androidXCompose"
implementation "androidx.compose.material:material:$Versions.androidXCompose"
implementation "androidx.compose.material:material-icons-core:$Versions.androidXCompose"
implementation "androidx.compose.material:material-icons-extended:$Versions.androidXCompose"
// implementation "androidx.compose.ui:ui-tooling:$Versions.androidXCompose"
implementation "androidx.compose.ui:ui-tooling:1.0.0-beta09"
implementation "com.google.accompanist:accompanist-insets:0.13.0"

implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07'
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0-alpha03'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$Versions.androidXCompose"
kapt Libs.androidx_room_compiler
kapt Libs.androidx_hilt_compiler

Expand Down Expand Up @@ -182,8 +212,8 @@ dependencies {
implementation Libs.kotlinCoroutinesAndroid

// LeakCanary
debugImplementation Libs.leakCanary
implementation Libs.leakCanaryPlumberAndroid
// debugImplementation Libs.leakCanary
// implementation Libs.leakCanaryPlumberAndroid

// Logging
implementation Libs.slf4jAndroidLogger
Expand All @@ -200,6 +230,10 @@ kapt {
correctErrorTypes true
}

jacoco {
toolVersion = "0.8.7"
}

play {
def serviceAccountFileName = "google-play-api.json"
if (rootProject.file(serviceAccountFileName).exists()) {
Expand Down
29 changes: 17 additions & 12 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar">
<activity android:name=".MainActivity">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand All @@ -30,6 +32,7 @@
android:name=".appwidget.ClickHandlingActivity"
android:allowTaskReparenting="false"
android:excludeFromRecents="true"
android:exported="true"
android:noHistory="true"
android:taskAffinity=""
android:theme="@android:style/Theme.NoDisplay">
Expand All @@ -46,13 +49,17 @@
android:taskAffinity=""
android:theme="@style/AppTheme.Dialog.NoActionBar" />

<activity android:name=".widgets.WidgetConfigActivity">
<activity
android:name=".widgets.ui.WidgetConfigActivity"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>

<receiver android:name=".appwidget.DDWidgetProvider">
<receiver
android:name=".appwidget.DDWidgetProvider"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
Expand All @@ -65,21 +72,19 @@
android:name=".receivers.UpdateReceiver"
android:exported="false" />

<receiver
android:name=".receivers.PinWidgetSuccessReceiver"
android:exported="false" />

<service
android:name=".appwidget.WidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />

<!-- Disable auto-init of WorkManager -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.impl.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />

<!-- Configure Firebase Analytics -->
<meta-data
Expand Down
41 changes: 4 additions & 37 deletions app/src/main/java/de/psdev/devdrawer/BaseFragment.kt
Original file line number Diff line number Diff line change
@@ -1,59 +1,26 @@
package de.psdev.devdrawer

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
import de.psdev.devdrawer.analytics.TrackingService
import javax.inject.Inject

abstract class BaseFragment<T : ViewBinding> : Fragment() {
open class BaseFragment : Fragment() {

@Inject
lateinit var trackingService: TrackingService

private var _binding: T? = null
// This property is only valid between onCreateView and onDestroyView.
protected val binding get() = _binding!!

protected var toolbarTitle: CharSequence
get() = requireActivity().title
set(value) {
requireActivity().title = value
}

final override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = createViewBinding(inflater, container, savedInstanceState).also { viewBinding ->
_binding = viewBinding
}.root

protected abstract fun createViewBinding(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): T

@CallSuper
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
val Fragment.viewLifecycleScope: LifecycleCoroutineScope
get() = viewLifecycleOwner.lifecycleScope

protected fun updateToolbarTitle(@StringRes resId: Int) {
requireActivity().setTitle(resId)
trackingService.trackScreen(this::class.java, getString(resId))
}

val Fragment.viewLifecycleScope: LifecycleCoroutineScope
get() = viewLifecycleOwner.lifecycleScope

}
}
17 changes: 10 additions & 7 deletions app/src/main/java/de/psdev/devdrawer/DevDrawerApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,23 @@ class DevDrawerApplication: Application(), Configuration.Provider {
registerAppInstallationReceiver()
setupWorkers()
}.let {
logger.warn("{} version {} ({}) took {}ms to init", this::class.java.simpleName, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, it)
logger.warn(
"{} version {} ({}) took {}ms to init",
this::class.java.simpleName,
BuildConfig.VERSION_NAME,
BuildConfig.VERSION_CODE,
it
)
}
}

// ==========================================================================================================================
// Configuration.Provider
// ==========================================================================================================================

override fun getWorkManagerConfiguration(): Configuration {
logger.warn { "getWorkManagerConfiguration" }
return Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
override fun getWorkManagerConfiguration(): Configuration = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()

// ==========================================================================================================================
// Private API
Expand Down
56 changes: 56 additions & 0 deletions app/src/main/java/de/psdev/devdrawer/DevDrawerScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package de.psdev.devdrawer

import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Grid3x3
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Widgets
import androidx.compose.ui.graphics.vector.ImageVector
import de.psdev.devdrawer.database.Widget
import de.psdev.devdrawer.database.WidgetProfile

sealed class DevDrawerScreen(
val route: String
)

sealed class TopLevelScreen(route: String): DevDrawerScreen(route) {
abstract val icon: ImageVector
@get:StringRes abstract val label: Int
}

object Widgets: TopLevelScreen(
route = "widgets"
) {
override val icon: ImageVector = Icons.Filled.Widgets
override val label: Int = R.string.widgets
}

object Profiles: TopLevelScreen(
route = "profiles"
) {
override val icon: ImageVector = Icons.Filled.Grid3x3
override val label: Int = R.string.profiles
}

object Settings: TopLevelScreen(
route = "settings"
) {
override val icon: ImageVector = Icons.Filled.Settings
override val label: Int = R.string.settings
}

object AppInfo: TopLevelScreen(
route = "info"
) {
override val icon: ImageVector = Icons.Filled.Info
override val label: Int = R.string.app_info
}

data class WidgetEditorDestination(
val widget: Widget
): DevDrawerScreen(route = "widgets/${widget.id}")

data class ProfileEditorDestination(
val widgetProfile: WidgetProfile
): DevDrawerScreen(route = "profiles/${widgetProfile.id}")
Loading

0 comments on commit ec250b8

Please sign in to comment.