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 May 28, 2021
1 parent 442f44f commit 30fdab8
Show file tree
Hide file tree
Showing 54 changed files with 1,759 additions and 1,032 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
30 changes: 26 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
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'

Expand All @@ -28,10 +27,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 @@ -47,6 +51,7 @@ android {
"-Xopt-in=kotlinx.coroutines.FlowPreview",
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
]
useIR = true
}
testOptions {
unitTests {
Expand Down Expand Up @@ -105,6 +110,9 @@ android {
exclude '**/NOTICE.txt'
exclude '**/*.gwt.xml'
}
composeOptions {
kotlinCompilerExtensionVersion Versions.androidXCompose
}
}

dependencies {
Expand Down Expand Up @@ -136,17 +144,31 @@ dependencies {
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.3.0'
implementation 'androidx.activity:activity-compose:1.3.0-alpha08'
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.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha05'
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0-alpha02'
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 +204,8 @@ dependencies {
implementation Libs.kotlinCoroutinesAndroid

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

// Logging
implementation Libs.slf4jAndroidLogger
Expand Down
16 changes: 7 additions & 9 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,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
37 changes: 37 additions & 0 deletions app/src/main/java/de/psdev/devdrawer/ViewBindingBaseFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
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.viewbinding.ViewBinding

abstract class ViewBindingBaseFragment<T : ViewBinding> : BaseFragment() {

private var _binding: T? = null

// This property is only valid between onCreateView and onDestroyView.
protected val binding get() = _binding!!

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
}

}
4 changes: 2 additions & 2 deletions app/src/main/java/de/psdev/devdrawer/about/AboutFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder
import com.mikepenz.aboutlibraries.util.LibsListenerImpl
import dagger.hilt.android.AndroidEntryPoint
import de.psdev.devdrawer.BaseFragment
import de.psdev.devdrawer.R
import de.psdev.devdrawer.ViewBindingBaseFragment
import de.psdev.devdrawer.databinding.FragmentAboutBinding
import de.psdev.devdrawer.utils.consume

@AndroidEntryPoint
class AboutFragment : BaseFragment<FragmentAboutBinding>() {
class AboutFragment : ViewBindingBaseFragment<FragmentAboutBinding>() {

override fun createViewBinding(
inflater: LayoutInflater,
Expand Down
39 changes: 6 additions & 33 deletions app/src/main/java/de/psdev/devdrawer/appwidget/DDWidgetProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@ import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.graphics.Color
import android.net.Uri
import android.widget.RemoteViews
import dagger.hilt.android.AndroidEntryPoint
import de.psdev.devdrawer.R
import de.psdev.devdrawer.database.DevDrawerDatabase
import de.psdev.devdrawer.database.Widget
import de.psdev.devdrawer.database.WidgetProfile
import de.psdev.devdrawer.receivers.UpdateReceiver
import de.psdev.devdrawer.utils.Constants
import de.psdev.devdrawer.utils.textColorForBackground
import de.psdev.devdrawer.widgets.WidgetConfigActivity
import kotlinx.coroutines.Dispatchers
Expand All @@ -41,34 +38,6 @@ class DDWidgetProvider : AppWidgetProvider() {
// AppWidgetProvider
// ==========================================================================================================================

override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
when (intent.action) {
Constants.ACTION_WIDGET_PINNED -> GlobalScope.launch(Dispatchers.IO) {
val widgetDao = devDrawerDatabase.widgetDao()
val widgetProfileDao = devDrawerDatabase.widgetProfileDao()
val defaultWidgetProfile = widgetProfileDao.findAll().firstOrNull()
?: WidgetProfile(name = "Default").also {
widgetProfileDao.insert(it)
}
val widgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID
)

// Create entries in database
val widget = Widget(
id = widgetId,
name = "Widget $widgetId",
color = Color.BLACK,
profileId = defaultWidgetProfile.id
)
widgetDao.insert(widget)
UpdateReceiver.send(context)
}
}
}

override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
GlobalScope.launch(Dispatchers.IO) {
Expand Down Expand Up @@ -126,8 +95,12 @@ class DDWidgetProvider : AppWidgetProvider() {
val configActivityIntent = WidgetConfigActivity.createStartIntent(context, widget.id)
configActivityIntent.putExtra("from_widget", true)
configActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK)
val configActivityPendingIntent =
PendingIntent.getActivity(context, 0, configActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val configActivityPendingIntent = PendingIntent.getActivity(
context,
0,
configActivityIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
widgetView.setOnClickPendingIntent(R.id.btn_settings, configActivityPendingIntent)

// Apps list
Expand Down
7 changes: 6 additions & 1 deletion app/src/main/java/de/psdev/devdrawer/database/WidgetDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package de.psdev.devdrawer.database

import androidx.room.Dao
import androidx.room.Query
import androidx.room.Transaction
import kotlinx.coroutines.flow.Flow

@Dao
abstract class WidgetDao : BaseDao<Widget>() {
abstract class WidgetDao: BaseDao<Widget>() {

@Query("SELECT * FROM widgets")
abstract suspend fun findAll(): List<Widget>
Expand All @@ -19,6 +20,10 @@ abstract class WidgetDao : BaseDao<Widget>() {
@Query("SELECT * FROM widgets WHERE id = :id")
abstract suspend fun findById(id: Int): Widget?

@Transaction
@Query("SELECT * FROM widgets WHERE id = :id")
abstract fun widgetWithIdObservable(id: Int): Flow<Widget>

@Query("DELETE FROM widgets WHERE id IN (:ids)")
abstract suspend fun deleteByIds(ids: List<Int>)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package de.psdev.devdrawer.database

import androidx.room.Dao
import androidx.room.Query
import androidx.room.Transaction
import kotlinx.coroutines.flow.Flow

@Dao
abstract class WidgetProfileDao: BaseDao<WidgetProfile>() {
abstract class WidgetProfileDao : BaseDao<WidgetProfile>() {
@Query("SELECT * FROM widget_profiles")
abstract suspend fun findAll(): List<WidgetProfile>

Expand All @@ -15,4 +16,8 @@ abstract class WidgetProfileDao: BaseDao<WidgetProfile>() {
@Query("SELECT * FROM widget_profiles WHERE id = :id")
abstract suspend fun findById(id: String): WidgetProfile?

@Transaction
@Query("SELECT * FROM widget_profiles WHERE id = :id")
abstract fun widgetProfileWithIdObservable(id: String): Flow<WidgetProfile>

}
Loading

0 comments on commit 30fdab8

Please sign in to comment.