Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4066cbb
upgrade to java 21, AGP 8.2.2, gradle 8.5
Sov1etB0mb3 May 24, 2026
e86d231
Merge pull request #1 from Sov1etB0mb3/khanh_dev
Sov1etB0mb3 May 24, 2026
32235e6
thêm UI phép tính nâng cao, UI lưới 5x5, thêm icon chuyển đổi chế độ
Chinhchinhs May 24, 2026
2a2794c
Merge pull request #2 from Sov1etB0mb3/feature/advanced-panel
Sov1etB0mb3 May 24, 2026
d0fe9ec
add tinh nhieu so lien tuc
Sov1etB0mb3 May 24, 2026
6973e74
Merge pull request #3 from Sov1etB0mb3/feature/advanced-panel
Chinhchinhs May 24, 2026
d4f2abd
Merge pull request #4 from Sov1etB0mb3/khanh_dev
Sov1etB0mb3 May 24, 2026
2b28280
feat: Thêm menu Cài đặt và logic chuyển đổi Dark/Light mode
Chinhchinhs May 24, 2026
00af753
Merge branch 'develop_devchinhs' into feature/theme-settings
Sov1etB0mb3 May 24, 2026
9fd86ab
Merge pull request #5 from Sov1etB0mb3/feature/theme-settings
Sov1etB0mb3 May 24, 2026
c3cf93e
Merge branch 'main' into develop_devchinhs
Sov1etB0mb3 May 24, 2026
5fc5d71
Merge pull request #6 from Sov1etB0mb3/develop_devchinhs
Sov1etB0mb3 May 24, 2026
655528a
fix error at text
Sov1etB0mb3 May 24, 2026
30c863d
fix: Tối ưu màu sắc động và padding cho CalculatorButton tương thích …
Chinhchinhs May 24, 2026
1cc8514
Merge pull request #7 from Sov1etB0mb3/develop_devchinhs
Chinhchinhs May 24, 2026
507b347
Merge branch 'main' of https://github.com/Sov1etB0mb3/Jetpack-Compose…
Sov1etB0mb3 May 24, 2026
df5bfa8
change current complex algorithm into Shunting-yard algorithm
Sov1etB0mb3 May 24, 2026
48978d8
Merge pull request #8 from Sov1etB0mb3/khanh_test
Sov1etB0mb3 May 24, 2026
3b15815
fix: Tái cấu trúc Theme, chuyển padding vào Box nội bộ để fix triệt đ…
Chinhchinhs May 25, 2026
e1dfa9e
Merge pull request #9 from Sov1etB0mb3/feature/fix-ui-performance
Sov1etB0mb3 May 25, 2026
45047cc
add square root, factorial, square, trigonometry and pi
Sov1etB0mb3 May 25, 2026
9055328
change multiply symbol into * instead x
Sov1etB0mb3 May 25, 2026
5a48f38
Merge pull request #10 from Sov1etB0mb3/khanh_test
Sov1etB0mb3 May 25, 2026
5e6d815
update readme
Sov1etB0mb3 May 25, 2026
7f4477a
Update README with light and dark theme information
Sov1etB0mb3 May 25, 2026
e827b86
add ci git action
Sov1etB0mb3 May 25, 2026
a0594ac
Merge pull request #11 from Sov1etB0mb3/khanh_test
Sov1etB0mb3 May 25, 2026
c749a96
fix: khac phục lag giao diện
Chinhchinhs May 25, 2026
04d0400
move the calculation logic out of viewmodel for better structure and …
Sov1etB0mb3 May 26, 2026
2a711a0
Merge pull request #12 from Sov1etB0mb3/khanh_test
Sov1etB0mb3 May 26, 2026
26aa8a0
add Unit Test
Sov1etB0mb3 May 26, 2026
7bd8cb1
Merge pull request #13 from Sov1etB0mb3/khanh_test
Sov1etB0mb3 May 26, 2026
5170b95
update workflow
Sov1etB0mb3 May 26, 2026
702b79d
Merge pull request #15 from Sov1etB0mb3/khanh_test
Sov1etB0mb3 May 26, 2026
4dea20c
add integration test
Sov1etB0mb3 May 26, 2026
52b3a22
Merge pull request #16 from Sov1etB0mb3/khanh_test
Sov1etB0mb3 May 26, 2026
9a53891
Merge pull request #17 from Sov1etB0mb3/feature/fix_lag
Sov1etB0mb3 May 26, 2026
69437a2
fix integration test
Sov1etB0mb3 May 26, 2026
5bf58da
add missing testcase
Sov1etB0mb3 May 26, 2026
edf4adc
add missing testcase
Sov1etB0mb3 May 26, 2026
fcc6d82
Merge pull request #18 from Sov1etB0mb3/khanh_test
Sov1etB0mb3 May 26, 2026
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
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: 21
distribution: temurin

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Build and run unit tests
run: ./gradlew assembleDebug test
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ A fully functional calculator app built with Jetpack Compose, following modern A
- Clean, Material Design 3 UI built entirely with Jetpack Compose
- State managed via ViewModel — survives configuration changes
- Supports chained operations and decimal inputs
- Trigonometry function, factorial, square and square root (updated)
- Light and Dark theme is available now!
- Able to keep the expression after calculation and prepare for the upcomming calculation

## 🛠 Tech Stack

Expand All @@ -29,9 +32,13 @@ A fully functional calculator app built with Jetpack Compose, following modern A
```bash
git clone https://github.com/santhoshj001/Jetpack-Compose-Calculator.git
```
2. Open in **Android Studio Hedgehog** or later
3. Let Gradle sync
4. Run on an emulator or physical device (API 21+)
2. Install JDK 21
3. Open in **Android Studio Hedgehog** or later
4. Change AGP to 8.2.2 and Gradle to 8.5
5. ![Uploading image.png…]()

6. Let Gradle sync
7. Run on an emulator or physical device (API 21+)

## 📄 License

Expand Down
36 changes: 18 additions & 18 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ plugins {
}

android {
compileSdk 32
namespace 'com.teamb.calculator'
compileSdk 34

defaultConfig {
applicationId "com.teamb.calculator"
minSdk 31
targetSdk 32
targetSdk 34
versionCode 1
versionName "1.0"

Expand All @@ -36,7 +37,7 @@ android {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerExtensionVersion "1.5.8"
}
packagingOptions {
resources {
Expand All @@ -46,19 +47,18 @@ android {
}

dependencies {

implementation 'androidx.core:core-ktx:1.7.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation 'androidx.compose.material3:material3:1.0.0-alpha01'
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1'
implementation 'androidx.core:core-splashscreen:1.0.0-rc01'
implementation 'androidx.core:core-ktx:1.12.0'
implementation "androidx.compose.ui:ui:1.5.4"
implementation 'androidx.compose.material3:material3:1.1.2'
implementation "androidx.compose.ui:ui-tooling-preview:1.5.4"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
implementation 'androidx.activity:activity-compose:1.8.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2'
implementation 'androidx.core:core-splashscreen:1.0.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
}
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.5.4"
debugImplementation "androidx.compose.ui:ui-tooling:1.5.4"
debugImplementation "androidx.compose.ui:ui-test-manifest:1.5.4"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package com.teamb.calculator

import androidx.compose.ui.test.*
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class CalculatorIntegrationTest {

@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()

private fun assertDisplay(expected: String) {
composeTestRule.onNode(
hasText(expected, substring = false),
useUnmergedTree = true
).assertExists()
}

@Test
fun basicAddition() {
composeTestRule.onNodeWithText("7").performClick()
composeTestRule.onNodeWithText("+").performClick()
composeTestRule.onNodeWithText("3").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("10.0")
}

@Test
fun pemdas() {
composeTestRule.onNodeWithText("3").performClick()
composeTestRule.onNodeWithText("+").performClick()
composeTestRule.onNodeWithText("4").performClick()
composeTestRule.onNodeWithText("*").performClick()
composeTestRule.onNodeWithText("2").performClick()
composeTestRule.onNodeWithText("-").performClick()
composeTestRule.onNodeWithText("6").performClick()
composeTestRule.onNodeWithText("/").performClick()
composeTestRule.onNodeWithText("3").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("9.0")
}

@Test
fun decimal() {
composeTestRule.onNodeWithText("2").performClick()
composeTestRule.onNodeWithText(".").performClick()
composeTestRule.onNodeWithText("5").performClick()
composeTestRule.onNodeWithText("+").performClick()
composeTestRule.onNodeWithText("3").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("5.5")
}

@Test
fun chainingAfterResult() {
composeTestRule.onNodeWithText("3").performClick()
composeTestRule.onNodeWithText("+").performClick()
composeTestRule.onNodeWithText("4").performClick()
composeTestRule.onNodeWithText("=").performClick()
composeTestRule.onNodeWithText("+").performClick()
composeTestRule.onNodeWithText("5").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("12.0")
}

@Test
fun factorial() {
composeTestRule.onNodeWithContentDescription("Expand", substring = true).performClick()
composeTestRule.onNodeWithText("5").performClick()
composeTestRule.onNodeWithText("!").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("120.0")
}

@Test
fun square() {
composeTestRule.onNodeWithContentDescription("Expand", substring = true).performClick()
composeTestRule.onNodeWithText("5").performClick()
composeTestRule.onNodeWithText("x²").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("25.0")
}

@Test
fun pi() {
composeTestRule.onNodeWithContentDescription("Expand", substring = true).performClick()
composeTestRule.onNodeWithText("π").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("3.14159265")
}

@Test
fun sin() {
composeTestRule.onNodeWithContentDescription("Expand", substring = true).performClick()
composeTestRule.onNodeWithText("sin").performClick()
composeTestRule.onNodeWithText("3").performClick()
composeTestRule.onNodeWithText("0").performClick()
composeTestRule.onNodeWithText(")").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("0.5")
}
@Test
fun cos() {
composeTestRule.onNodeWithContentDescription("Expand").performClick()
composeTestRule.onNodeWithText("cos").performClick()
composeTestRule.onNodeWithText("9").performClick()
composeTestRule.onNodeWithText("0").performClick()
composeTestRule.onNodeWithText(")").performClick()
composeTestRule.onNodeWithText("=").performClick()
// composeTestRule.onNodeWithTag("Result").assertTextEquals("0.0")
assertDisplay("0.0")
}

@Test
fun tan() {
composeTestRule.onNodeWithContentDescription("Expand").performClick()
composeTestRule.onNodeWithText("tan").performClick()
composeTestRule.onNodeWithText("4").performClick()
composeTestRule.onNodeWithText("5").performClick()
composeTestRule.onNodeWithText(")").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("1.0")
}
@Test
fun sqrt() {
composeTestRule.onNodeWithContentDescription("Expand", substring = true).performClick()
composeTestRule.onNodeWithText("√").performClick()
composeTestRule.onNodeWithText("9").performClick()
composeTestRule.onNodeWithText(")").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("3.0")
}

@Test
fun factorialInExpression() {
composeTestRule.onNodeWithContentDescription("Expand", substring = true).performClick()
composeTestRule.onNodeWithText("3").performClick()
composeTestRule.onNodeWithText("+").performClick()
composeTestRule.onNodeWithText("4").performClick()
composeTestRule.onNodeWithText("!").performClick()
composeTestRule.onNodeWithText("=").performClick()
assertDisplay("27.0")
}
@Test
fun clear() {
composeTestRule.onNodeWithText("7").performClick()
composeTestRule.onNodeWithText("+").performClick()
composeTestRule.onNodeWithText("3").performClick()
composeTestRule.onNodeWithText("AC").performClick()
assertDisplay("")
}

}

This file was deleted.

3 changes: 1 addition & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.teamb.calculator">
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
Expand Down
Loading