Skip to content
Merged
Show file tree
Hide file tree
Changes from 88 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
ae0525e
add: Glance 기본 세팅
HI-JIN2 Feb 23, 2025
315645e
add: glance preview 추가
HI-JIN2 Feb 23, 2025
8fae0eb
feat: glance widget UI 구현 중
HI-JIN2 Feb 23, 2025
59edc7d
feat: worker 및 datastore
HI-JIN2 Feb 25, 2025
3e5c2fc
feat: lazyColumn 구현 완료
HI-JIN2 Feb 25, 2025
b1c8de7
chore: 리시버 정리
HI-JIN2 Feb 26, 2025
6d4839e
feat: 변경된 디자인 4*2
HI-JIN2 Feb 26, 2025
4bdedee
setting: hilt compiler 추가
HI-JIN2 Feb 26, 2025
5966c2c
feat: Worker에서 Usecase로 API 호출하고, datastore에 저장
HI-JIN2 Mar 1, 2025
66fae76
add: TaskMoule
HI-JIN2 Mar 1, 2025
08cb069
feat: 위젯 UI BaseLayout을 재활용 하도록 수정
HI-JIN2 Mar 1, 2025
cffddec
feat: 더미가 아닌 실제 데이터를 연결
HI-JIN2 Mar 1, 2025
4b9713c
chore: 코드 정리
HI-JIN2 Mar 1, 2025
374a40a
feat: data class WidgetMeal 만듦
HI-JIN2 Mar 1, 2025
b31feac
chore: 코드 정리
HI-JIN2 Mar 1, 2025
0955b79
chore: enum -> 한글화 함수 추가
HI-JIN2 Mar 1, 2025
69f43cf
feat: 작은 위젯 추가
HI-JIN2 Mar 5, 2025
5c1fc45
feat: 위젯 설정 화면
HI-JIN2 Mar 5, 2025
1f4c25f
add: WidgetSettingScreen
HI-JIN2 Mar 5, 2025
37cd1a1
setting: 라이브러리 정리 (hilt)
HI-JIN2 Jun 25, 2025
9d92f9d
feat: 일단 빌드 됨
HI-JIN2 Jun 25, 2025
99251cb
feat: json 파싱 됨
HI-JIN2 Jul 1, 2025
72decae
add: Glance 기본 세팅
HI-JIN2 Feb 23, 2025
672d22c
add: glance preview 추가
HI-JIN2 Feb 23, 2025
aa8a0e5
feat: glance widget UI 구현 중
HI-JIN2 Feb 23, 2025
6588456
feat: worker 및 datastore
HI-JIN2 Feb 25, 2025
f6c5b50
feat: lazyColumn 구현 완료
HI-JIN2 Feb 25, 2025
0cfadd2
chore: 리시버 정리
HI-JIN2 Feb 26, 2025
3d4a8e6
feat: 변경된 디자인 4*2
HI-JIN2 Feb 26, 2025
a00bcb5
feat: Worker에서 Usecase로 API 호출하고, datastore에 저장
HI-JIN2 Mar 1, 2025
485a50c
feat: 위젯 UI BaseLayout을 재활용 하도록 수정
HI-JIN2 Mar 1, 2025
a5a0508
feat: 더미가 아닌 실제 데이터를 연결
HI-JIN2 Mar 1, 2025
ab9eaca
chore: 코드 정리
HI-JIN2 Mar 1, 2025
52fe598
feat: data class WidgetMeal 만듦
HI-JIN2 Mar 1, 2025
a209a81
chore: 코드 정리
HI-JIN2 Mar 1, 2025
c240346
chore: enum -> 한글화 함수 추가
HI-JIN2 Mar 1, 2025
edf514b
feat: 작은 위젯 추가
HI-JIN2 Mar 5, 2025
f3a979e
feat: 위젯 설정 화면
HI-JIN2 Mar 5, 2025
9b643ec
add: WidgetSettingScreen
HI-JIN2 Mar 5, 2025
f2a1e06
feat: 일단 빌드 됨
HI-JIN2 Jun 25, 2025
8f6952e
setting: library 정리
HI-JIN2 Jul 1, 2025
980d512
feat: 디자인 반영
HI-JIN2 Jul 1, 2025
dff569a
feat: resize 반영 3*2 ~ 5*2
HI-JIN2 Jul 1, 2025
f0afeae
feat: 시간 변경
HI-JIN2 Jul 1, 2025
2e93c4a
feat: resize 3~5 * 2
HI-JIN2 Jul 1, 2025
47abf7c
delete: save 관련 로직 제거
HI-JIN2 Jul 1, 2025
79e0fc4
feat: 위젯 클릭시 앱 실행
HI-JIN2 Jul 1, 2025
8a1b532
feat: 색상 및 padding
HI-JIN2 Jul 2, 2025
bae53ed
chore: MealService에 토큰 붙이지 않도록 수정
HI-JIN2 Jul 6, 2025
62ebf57
chore: 에러 화면도 클릭 시 앱 진입 하도록
HI-JIN2 Jul 6, 2025
aa23fc7
feat: meal 단위 분리 및 같은 meal 안에서는 +로 합치기
HI-JIN2 Jul 6, 2025
1bdb78d
feat: 식당명 하드코딩 아니게 수정
HI-JIN2 Jul 6, 2025
e408df4
feat: < > 눌렀을때 바로 반영됨
HI-JIN2 Jul 6, 2025
6f659a8
feat: < > 눌렀을때 위젯 ui 상의 이름이랑 메뉴들도 바뀜 + 로그도 당연히 다 뜸
HI-JIN2 Jul 6, 2025
861a488
fix: 식당 이름만 잘 안바뀌던 문제 해결
HI-JIN2 Jul 6, 2025
d55e4ab
refactor: MealWidgetScaffold로 중복코드 처리
HI-JIN2 Jul 6, 2025
f97d27b
fix: 위젯 끼리 동기화 되는 현상 고침 (glanceId를 주고 받도록 수정)
HI-JIN2 Jul 8, 2025
1717328
feat: 오른쪽도 추가
HI-JIN2 Jul 8, 2025
e437601
repackaging
HI-JIN2 Jul 11, 2025
8d7dbd2
chore: more prettier code
HI-JIN2 Jul 11, 2025
c349598
feat: create component
HI-JIN2 Jul 27, 2025
5d89d8b
feat: setting configure
HI-JIN2 Jul 27, 2025
2998fd3
chore: repackaging
HI-JIN2 Jul 27, 2025
6e6e6f0
feat: Custom Radio Button success
HI-JIN2 Jul 27, 2025
ef759c1
feat: widget add scenario
HI-JIN2 Jul 27, 2025
5538055
fix: init default (dodam)
HI-JIN2 Jul 27, 2025
68ab3d5
chore: separate core/design-system module
HI-JIN2 Aug 20, 2025
eef38a3
chore: change default ""
HI-JIN2 Aug 20, 2025
fe61eb0
chore: change preview image
HI-JIN2 Aug 20, 2025
2ae1677
refactor: separate TopBar
HI-JIN2 Aug 20, 2025
084f497
chore: 의존성 정리
HI-JIN2 Aug 25, 2025
535f791
setting: cleaned libs
HI-JIN2 Aug 26, 2025
6c9a1b3
chore: top bar
HI-JIN2 Aug 26, 2025
22e8b0b
Revert "chore: top bar"
HI-JIN2 Aug 26, 2025
6c8c01f
chore: top bar
HI-JIN2 Aug 26, 2025
dda9ea5
feat: 설정 없음 -> 액션 가하면 정상작동
HI-JIN2 Aug 26, 2025
41e9e2f
feat: 아침/점심/저녁 다 datastore에 저장
HI-JIN2 Aug 26, 2025
fc1f897
feat: 딜레이 5초
HI-JIN2 Aug 26, 2025
2e3cc18
Merge branch 'develop' into feat/advanced-widget
HI-JIN2 Aug 31, 2025
52a2a1c
feat: 딜레이 2초
HI-JIN2 Aug 31, 2025
c2d7141
chore: package
HI-JIN2 Aug 31, 2025
c656cea
chore: change same minsdk
HI-JIN2 Aug 31, 2025
8050c8d
chore: change same compose options
HI-JIN2 Aug 31, 2025
4d767a0
fix: 바탕화면에 배치된 위젯을 삭제할시 엉뚱한 파일명 기준으로 datastore를 삭제해서 삭제가 안되던문제 해결
HI-JIN2 Sep 4, 2025
a5d49fd
chore: 패키지명 fullname으로 작성된 것을 import로 변경
HI-JIN2 Sep 4, 2025
e4e8ea4
Merge branch 'develop' into feat/advanced-widget
HI-JIN2 Sep 4, 2025
85066d6
refactor: datastore 접근을 ui(widget)레이어에서 하지 않고 data/domain 계층을 추가하여 분리함
HI-JIN2 Sep 4, 2025
e445acc
refactor: TodayMeal 로직 클린하게 변경
HI-JIN2 Sep 4, 2025
6054c4a
chore: delete unused
HI-JIN2 Sep 4, 2025
71080fb
chore: 위젯 클릭시 바로가기
HI-JIN2 Sep 4, 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
104 changes: 62 additions & 42 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ plugins {
alias(libs.plugins.hilt.android)
id("kotlin-parcelize")
id("kotlin-android")
id("kotlin-kapt")
id("com.google.android.gms.oss-licenses-plugin")
id("kotlin-kapt")

}

android {
namespace = "com.eatssu.android"
compileSdk = 34
compileSdk = 35

// S8: API 28
// S21: API 33
Expand Down Expand Up @@ -47,12 +48,11 @@ android {
buildConfigField("String", "KAKAO_NATIVE_APP_KEY", "\"$kakaoKey\"")
manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = kakaoKey

isShrinkResources = false
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")

var shrinkResources = false
var minifyEnabled = false
Comment on lines +54 to +55
Copy link

Copilot AI Aug 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These variables are declared but never used. They should either be assigned to the build configuration properties or removed.

Suggested change
var shrinkResources = false
var minifyEnabled = false

Copilot uses AI. Check for mistakes.
}

debug {
Expand All @@ -68,8 +68,6 @@ android {
val kakaoKey: String = p.getProperty("KAKAO_NATIVE_APP_KEY")
buildConfigField("String", "KAKAO_NATIVE_APP_KEY", "\"$kakaoKey\"")
manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = kakaoKey

isMinifyEnabled = false
}
}

Expand All @@ -78,14 +76,18 @@ android {
targetCompatibility = JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = "17"
}

composeOptions {
kotlinCompilerExtensionVersion = "1.5.15"
}

kotlin {
jvmToolchain(17)
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}

splits {
abi {
isEnable = true
Expand All @@ -100,26 +102,34 @@ android {
}

dependencies {
implementation(project(":core:design-system"))

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.constraintlayout)
implementation(libs.androidx.constraintlayout)
implementation(libs.threetenabp)
implementation(libs.material.calendarview)
implementation(libs.recyclerview)
implementation(libs.androidx.recyclerview)
implementation(libs.transport.runtime)
implementation(libs.activity)
implementation(libs.fragment)
implementation(libs.androidx.activity)
implementation(libs.androidx.activity.ktx)
implementation(libs.androidx.fragment.ktx)

//glance
implementation(libs.androidx.glance)
implementation(libs.androidx.glance.preview)
implementation(libs.androidx.glance.appwidget)
implementation(libs.androidx.glance.material3)
debugImplementation(libs.androidx.glance.appwidget.preview) // 프리뷰 지원

// Testing libraries
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
androidTestImplementation(libs.androidx.espresso.core)

//retrofit2: 서버통신
implementation(libs.retrofit)
implementation(libs.converter.gson)
implementation(libs.retrofit.converter.gson)

// Gson for JSON parsing
implementation(libs.gson)
Expand All @@ -136,20 +146,23 @@ dependencies {
implementation(libs.compressor)

// Coroutines for concurrency
implementation(libs.coroutines)
implementation(libs.coroutines.core)
implementation(libs.lifecycle.runtime)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.androidx.lifecycle.runtime.ktx)

// Kakao login SDK
implementation(libs.kakao.login)

// Hilt for Dependency Injection
implementation(libs.hilt)
kapt(libs.hilt.compiler)
implementation(libs.hilt.android)
kapt(libs.hilt.android.compiler)
kapt(libs.androidx.hilt.compiler)
implementation(libs.androidx.hilt.common)
implementation(libs.androidx.hilt.work)

// ViewModel and LiveData
implementation(libs.lifecycle.viewmodel)
implementation(libs.lifecycle.livedata)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.lifecycle.livedata.ktx)

implementation(libs.play.services.base)

Expand All @@ -167,26 +180,33 @@ dependencies {

// Compose
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.animation)
implementation(libs.androidx.ui.tooling)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.lifecycle.runtime.ktx.v252)
implementation(libs.compose.bom)
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
androidTestImplementation(libs.androidx.ui.test.junit4)
implementation(libs.androidx.compose.animation)
implementation(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.compose.lifecycle.viewmodel)
implementation(libs.androidx.compose.lifecycle.runtime)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
// androidTestImplementation(libs.androidx.compose.ui.test.junit4)
Copy link

Copilot AI Aug 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out dependency should either be removed or uncommented if needed for testing.

Suggested change
// androidTestImplementation(libs.androidx.compose.ui.test.junit4)
androidTestImplementation(libs.androidx.compose.ui.test.junit4)

Copilot uses AI. Check for mistakes.
implementation(libs.compose.theme.adapter)
implementation(libs.accompanist.appcompat.theme)
androidTestImplementation(libs.compose.bom)
debugImplementation(libs.androidx.ui.test.manifest)
androidTestImplementation(libs.androidx.compose.bom)
debugImplementation(libs.androidx.compose.ui.test.manifest)

// navigation
implementation ("androidx.navigation:navigation-fragment:2.8.9")
implementation ("androidx.navigation:navigation-ui:2.8.9")
implementation(libs.androidx.navigation.fragment)
implementation(libs.androidx.navigation.ui)

// worker (Kotlin + coroutines)
implementation(libs.androidx.work.runtime.ktx)

//data store (with flow)
implementation(libs.androidx.datastore.preferences)

}

kapt {
correctErrorTypes = true
}
}
51 changes: 50 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

<!-- 이걸 추가하면 기기 재부팅 후에도 WorkManager가 다시 실행됨 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
android:name=".App"
android:allowBackup="true"
Expand All @@ -45,9 +48,13 @@
<meta-data android:name="photopicker_activity:0:required" android:value="" />
</service>


<!-- 오픈소스 -->
<meta-data
android:name="com.google.android.gms.oss.licenses.enabled"
android:value="true" />

<!-- 푸시알림 리시버 -->
<receiver
android:name=".alarm.NotificationReceiver"
android:enabled="true"
Expand All @@ -57,6 +64,36 @@
</intent-filter>
</receiver>

<!-- 위젯 리시버 -->
<receiver
android:name=".presentation.widget.MealWidgetReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>

<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />
</receiver>


<!-- 워커 매니저를 위한 프로바이더 -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="com.eatssu.android.androidx-startup"
tools:node="remove" />

<activity
android:name=".presentation.widget.ui.WidgetSettingActivity"
android:excludeFromRecents="true"
android:exported="true"
android:noHistory="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>

<activity
android:name=".presentation.mypage.DeveloperActivity"
android:exported="false" />
Expand All @@ -70,11 +107,23 @@
<activity
android:name=".presentation.login.IntroActivity"
android:exported="true">
<!-- 기본 런처 필터 -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- 딥링크 필터 -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="root"
android:scheme="eatssu" />
</intent-filter>
</activity>
<activity
android:name=".presentation.cafeteria.review.write.ReviewWriteRateActivity"
Expand Down
13 changes: 12 additions & 1 deletion app/src/main/java/com/eatssu/android/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.eatssu.android

import android.app.Application
import android.content.Context
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import com.eatssu.android.domain.model.TokenState
import com.eatssu.android.domain.model.TokenStateManager
import com.eatssu.android.presentation.base.TokenEventBus
Expand All @@ -16,10 +18,11 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

/** App: 앱이 살아있는 동안 공통 리소스 관리를 위한 클래스 */
@HiltAndroidApp
class App: Application() {
class App : Application(), Configuration.Provider {
companion object{
lateinit var appContext: Context //todo 이거 빼기
}
Expand All @@ -29,6 +32,9 @@ class App: Application() {
* */
private val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

@Inject
lateinit var workerFactory: HiltWorkerFactory

override fun onCreate() {
super.onCreate()
FirebaseApp.initializeApp(this)
Expand Down Expand Up @@ -60,4 +66,9 @@ class App: Application() {
}
}
}

override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class NotificationReceiver : BroadcastReceiver() {
)

val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_alarm_logo)
.setSmallIcon(R.drawable.ic_mini_logo)
.setContentTitle(context.getString(R.string.notification_context_title))
.setContentText(context.getString(R.string.notification_context_text))
.setPriority(NotificationCompat.PRIORITY_HIGH)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fun ArrayList<GetMealResponse>.mapTodayMenuResponseToMenu(): List<Menu> {

this.forEach { mealResponse ->
val menuNames =
mealResponse.briefMenus.joinToString(separator = "+") { it.name ?: "" }
mealResponse.briefMenus.joinToString(separator = " + ") { it.name ?: "" }
val mealId = mealResponse.mealId ?: -1
val price = mealResponse.price ?: 0
val mainRating = mealResponse.rating ?: 0.0
Expand All @@ -34,4 +34,11 @@ fun ArrayList<GetMealResponse>.mapTodayMenuResponseToMenu(): List<Menu> {
}

return menuList
}
}


fun ArrayList<GetMealResponse>.toDomain(): List<List<String>> {
return this.map { meal ->
meal.briefMenus.mapNotNull { it.name }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.eatssu.android.data.dto.response

import com.google.gson.annotations.SerializedName

data class TokenValidationResponse(
@SerializedName("isValid")
val isValid: Boolean
)
16 changes: 16 additions & 0 deletions app/src/main/java/com/eatssu/android/data/enums/Restaurant.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.eatssu.android.data.enums



enum class Restaurant(val displayName: String, val menuType: MenuType) {
HAKSIK("학생 식당", MenuType.VARIABLE),
DODAM("도담 식당", MenuType.VARIABLE),
Expand All @@ -8,4 +10,18 @@ enum class Restaurant(val displayName: String, val menuType: MenuType) {
FOOD_COURT("푸드 코트", MenuType.FIXED),
SNACK_CORNER("스낵 코너", MenuType.FIXED),
THE_KITCHEN("더 키친", MenuType.FIXED);

companion object {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ Etc ]

data모듈에서 UI <> 서버 <> 비즈니스 로직 간 매핑 함수들이 생겨난거군요 좋네욤


fun getVariableRestaurantList(): List<Restaurant> {
return entries.filter { it.menuType == MenuType.VARIABLE }
}

fun fromRestaurantEnumName(enumName: String): String {
Comment on lines +19 to +20
Copy link

Copilot AI Aug 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent indentation on line 19-20. The function declaration should align with the other companion object functions.

Suggested change
fun fromRestaurantEnumName(enumName: String): String {
fun fromRestaurantEnumName(enumName: String): String {

Copilot uses AI. Check for mistakes.
return entries.find { it.name == enumName }?.displayName ?: ""
}

fun fromDisplayName(name: String): String =
entries.find { it.displayName == name }?.name ?: error("Unknown display name: $name")
}
}
Loading