Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d3a31d9
Reduce warnings
dogtim Sep 11, 2022
5cf1212
Practice the Koin component
dogtim Sep 16, 2022
8539ae0
Refinement
dogtim Sep 16, 2022
1d2670f
Add the use case of the View Stub
dogtim Oct 9, 2022
6822db6
Merge commit '1d2670ffae032bdfd9ecc47cc8525deff37def87' into viewstub
dogtim Oct 9, 2022
091f0b3
Merge pull request #5 from dogtim/viewstub
dogtim Oct 9, 2022
01daa06
Fix app crash problem
dogtim Oct 9, 2022
3300796
Fix unit test compile problem
dogtim Oct 17, 2022
2071dec
Add unit test for "equal"
dogtim Oct 17, 2022
7093823
Compare the "class" and "data"
dogtim Oct 17, 2022
90c4d07
Create TabLayout for fun
dogtim Nov 10, 2022
e21f9d8
Create TabLayout for fun
dogtim Nov 10, 2022
30de3fb
Create TabLayout for fun
dogtim Nov 10, 2022
9637d12
Practice the parcelable
dogtim Nov 28, 2022
dbc2c28
Create codeball
dogtim Feb 24, 2023
75f6433
Update codeball.yml
dogtim Feb 24, 2023
c71b43e
Export to video by a bitmap
dogtim Mar 27, 2023
9e07efd
Make the bitmap scale to the mp4 setting
dogtim Mar 27, 2023
cb9f79c
Draw different bitmaps into video
dogtim Mar 27, 2023
4e1de35
Clear previous frame by
dogtim Mar 27, 2023
1b9d6d2
Move codes to view model
dogtim Mar 27, 2023
681b0a0
Give State for showing the loading progress indicator
dogtim Mar 29, 2023
3ebc94e
Rename Animation stuff to media
dogtim Mar 29, 2023
4c406f5
Rename
dogtim Mar 29, 2023
b4ddfd5
Finish the espresso to test the ui result
dogtim Mar 30, 2023
ad22d70
Refine testing codes
dogtim Mar 30, 2023
094c553
Create a testing application which we can inject the model we want to
dogtim Mar 30, 2023
55a7513
Refine codes
dogtim Mar 30, 2023
ac176e1
Reorganize the codes
dogtim Mar 30, 2023
eecf888
Provide compose activity
dogtim Mar 30, 2023
372f0c1
Integrate the preview function
dogtim Mar 30, 2023
d6e7102
Refine codes
dogtim Apr 10, 2023
adb5f51
Import the Flow for practicing
dogtim Apr 21, 2023
7c14999
Update settings
dogtim Sep 19, 2023
afca790
temp
dogtim Jun 30, 2025
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
21 changes: 21 additions & 0 deletions .github/workflows/codeball.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Codeball
on:
pull_request: {}
pull_request_review_comment:
types: [created, edited]

jobs:
codeball_job:
runs-on: ubuntu-latest
name: Codeball
steps:
# Run Codeball on all new Pull Requests and Review Comments! 🚀
# For customizations and more documentation, see https://github.com/sturdy-dev/codeball-action
- name: Codeball
uses: sturdy-dev/codeball-action@v2
with:
approvePullRequests: "true"
labelPullRequestsWhenApproved: "true"
labelPullRequestsWhenReviewNeeded: "false"
failJobsWhenReviewNeeded: "false"
codeSuggestionsFromComments: "true"
Comment thread
dogtim marked this conversation as resolved.
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

101 changes: 61 additions & 40 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,27 @@ plugins {
}

android {
compileSdk 32
compileSdk 33

defaultConfig {
applicationId "com.example.associate.training"
minSdk 21
targetSdk 32
targetSdk 33
versionCode 1
versionName "1.0"
// For androidx.renderscript.
renderscriptTargetApi 11
renderscriptSupportModeEnabled true

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "com.example.associate.training.InstrumentationTestRunner"
}
buildFeatures {
viewBinding true
dataBinding true
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.2"
}
buildTypes {
release {
Expand All @@ -36,58 +40,75 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '18'
}
namespace 'com.example.associate.training'
}

dependencies {
// ViewModel
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.activity:activity-ktx:1.4.0"
// WorkInfo, WorkManager
implementation "androidx.work:work-runtime-ktx:2.7.1"
// AndroidX Libraries
implementation "androidx.core:core-ktx:1.7.0"
implementation "androidx.appcompat:appcompat:1.4.1"
implementation "com.google.android.material:material:1.6.0"
implementation "androidx.constraintlayout:constraintlayout:2.1.3"
// Compose
def compose_ui_version = '1.4.0'
implementation "androidx.compose.ui:ui:$compose_ui_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
implementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
implementation 'androidx.activity:activity-compose:1.7.0'
implementation 'androidx.compose.material:material:1.4.0'

// androidx.navigation, NavController
// Navigation
def nav_version = "2.4.2"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

// ViewModel and Lifecycle
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.activity:activity-ktx:1.4.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"

// Room libraries
//
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"

// WorkManager
implementation "androidx.work:work-runtime-ktx:2.7.1"

// Room and DataStore
def room_version = "2.5.1"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
// Image Loader
implementation "androidx.datastore:datastore-preferences:1.0.0"

// Image Loading
implementation "io.coil-kt:coil:2.1.0"

// Moshi
// JSON Parsing
def moshi_version = "1.12.0"
implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
// Retrofit with Moshi Converter
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"

implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
// Gson
implementation 'com.google.code.gson:gson:2.8.9'

// DataStore
implementation "androidx.datastore:datastore-preferences:1.0.0"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"

// Testing-only dependencies
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.navigation:navigation-testing:2.4.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation "androidx.test:core:$test_core_version"
androidTestImplementation "androidx.test:runner:$test_core_version"
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espresso_version"
implementation "com.squareup.retrofit2:converter-moshi:2.9.0"
implementation "com.google.code.gson:gson:2.8.9"

androidTestImplementation 'androidx.navigation:navigation-testing:2.4.2'
// Dependency Injection
def koin_version = "3.1.2"
implementation "io.insert-koin:koin-android:$koin_version"
testImplementation "io.insert-koin:koin-test:$koin_version"
androidTestImplementation "io.insert-koin:koin-test:$koin_version"
testImplementation "io.insert-koin:koin-test-junit4:$koin_version"

debugImplementation 'androidx.fragment:fragment-testing:1.4.1'
// glide
implementation 'com.github.bumptech.glide:glide:4.13.2'
// Testing Dependencies
def junit_version = "4.13.2"
testImplementation "junit:junit:$junit_version"
androidTestImplementation "androidx.test.ext:junit:1.1.3"
androidTestImplementation "androidx.test:core:1.4.0"
androidTestImplementation "androidx.test:runner:1.4.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
androidTestImplementation "androidx.test.espresso:espresso-contrib:3.4.0"
debugImplementation "androidx.fragment:fragment-testing:1.4.1"

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.example.associate.training

import android.view.View
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.associate.training.media.MediaActivity
import com.google.android.material.progressindicator.CircularProgressIndicator
import org.hamcrest.Description
import org.hamcrest.Matchers.allOf
import org.hamcrest.TypeSafeMatcher
import org.junit.Assert.*
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MediaActivityTest {

@get:Rule
val activity = ActivityScenarioRule(MediaActivity::class.java)

@Test
fun testEncoding() {

val startTime = System.currentTimeMillis()
var clicked = false
val progressIndicator = onView(withId(R.id.progress_indicator))
val button = onView(withId(R.id.export_to_video))
while (!clicked && System.currentTimeMillis() - startTime < 10000) {
try {
button.check(matches(allOf(isClickable(), isDisplayed())))
button.perform(click())
// We need to wait for the progress indicator to be displayed because sometimes performing click is not working
progressIndicator.check(matches(object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description?) {
description?.appendText("Indeterminate progress bar")
}

override fun matchesSafely(item: View?): Boolean {
return item is CircularProgressIndicator && item.isIndeterminate
}
}))
clicked = true
} catch (e: Throwable) {
Thread.sleep(100)
}
}

Thread.sleep(10000) // Wait for encoding to complete (adjust time as needed)

// Verify that the "Complete" Toast is displayed
onView(withId(R.id.content)).check(matches(withText("Complete")))

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.example.associate.training

import android.os.Parcel
import android.os.Parcelable
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith

/**
* To have a custom model object which implements the interface Parcelable in order to pass objects between components
* (activities, fragments, services, etc…)
* See [medium](https://medium.com/@dbottillo/android-junit-parcelable-model-test-37a2f2ae18b1).
*/
@RunWith(AndroidJUnit4::class)
class ParcelableTest {

@Test
fun object_equal() {
val book = Book("author", "title")

val parcel = Parcel.obtain()
book.writeToParcel(parcel, book.describeContents())
parcel.setDataPosition(0)

val createdFromParcel = Book.createFromParcel(parcel)
assertEquals("author", createdFromParcel.author)
assertEquals("title", createdFromParcel.title)
}

@Test
fun test_subclass() {
val book = SubBook("author", "title", true)

val parcel = Parcel.obtain()
book.writeToParcel(parcel, book.describeContents())
parcel.setDataPosition(0)

val createdFromParcel = SubBook.createFromParcel(parcel)
assertEquals("author", createdFromParcel.author)
assertEquals("title", createdFromParcel.title)
assertEquals(true, createdFromParcel.isAdult)
}
}

open class Book : Parcelable {
val author: String
val title: String

constructor(author: String, title: String) {
this.author = author
this.title = title
}

constructor(`in`: Parcel) {
author = `in`.readString().toString()
title = `in`.readString().toString()
}

override fun describeContents(): Int {
return 0
}

override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeString(author)
dest.writeString(title)
}

companion object CREATOR : Parcelable.Creator<Book> {
override fun createFromParcel(parcel: Parcel) = Book(parcel)
override fun newArray(size: Int): Array<Book?> = arrayOfNulls(size)
}
}

class SubBook : Book {
var isAdult: Boolean = false

constructor(author: String, title: String, isAdult: Boolean) : super(author, title) {
this.isAdult = isAdult
}

constructor(`in`: Parcel) : super(`in`) {
isAdult = `in`.readBoolean()
}

override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeBoolean(isAdult)
}

companion object CREATOR : Parcelable.Creator<SubBook> {
override fun createFromParcel(parcel: Parcel) = SubBook(parcel)
override fun newArray(size: Int): Array<SubBook?> = arrayOfNulls(size)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.associate.training.core

import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner

class InstrumentationTestRunner : AndroidJUnitRunner() {
override fun newApplication(
classLoader: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(classLoader, TestApplication::class.java.name, context)
}
}
Loading