├── .github ├── ISSUE_TEMPLATE │ └── issue_template.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── org │ │ └── shortweather │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── org │ │ │ └── shortweather │ │ │ ├── ShortWeatherApplication.kt │ │ │ ├── data │ │ │ ├── api │ │ │ │ ├── AuthService.kt │ │ │ │ ├── CustomWeatherService.kt │ │ │ │ └── TodayWeatherService.kt │ │ │ ├── model │ │ │ │ ├── BaseResponse.kt │ │ │ │ ├── CustomWeather.kt │ │ │ │ ├── SettingTimeData.kt │ │ │ │ ├── TodayWeather.kt │ │ │ │ ├── UserData.kt │ │ │ │ └── WeeklyWeather.kt │ │ │ ├── repository │ │ │ │ ├── AuthRepositoryImpl.kt │ │ │ │ ├── CustomWeatherRepositoryImpl.kt │ │ │ │ └── TodayWeatherRepositoryImpl.kt │ │ │ └── source │ │ │ │ └── remote │ │ │ │ ├── AuthRemoteDataSource.kt │ │ │ │ ├── CustomWeatherRemoteDataSource.kt │ │ │ │ └── TodayWeatherRemoteDataSource.kt │ │ │ ├── di │ │ │ ├── NetworkModule.kt │ │ │ ├── RepositoryModule.kt │ │ │ └── ServiceModule.kt │ │ │ ├── domain │ │ │ └── repository │ │ │ │ ├── AuthRepository.kt │ │ │ │ ├── CustomWeatherRepository.kt │ │ │ │ └── TodayWeatherRepository.kt │ │ │ ├── presentation │ │ │ ├── MainActivity.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── alarmsetting │ │ │ │ ├── view │ │ │ │ │ └── AlarmSettingActivity.kt │ │ │ │ └── viewmodel │ │ │ │ │ └── AlarmSettingViewModel.kt │ │ │ ├── customweather │ │ │ │ ├── adapter │ │ │ │ │ ├── CustomWeatherPrecipitationAdapter.kt │ │ │ │ │ └── CustomWeatherTempAdapter.kt │ │ │ │ ├── view │ │ │ │ │ └── CustomWeatherFragment.kt │ │ │ │ └── viewmodel │ │ │ │ │ └── CustomWeatherViewModel.kt │ │ │ ├── input │ │ │ │ ├── adapter │ │ │ │ │ └── BottomSheetAdapter.kt │ │ │ │ ├── view │ │ │ │ │ ├── BottomSheetFragment.kt │ │ │ │ │ ├── BottomSheetTimeFragment.kt │ │ │ │ │ ├── InputInfoActivity.kt │ │ │ │ │ └── InputTimeActivity.kt │ │ │ │ └── viewmodel │ │ │ │ │ ├── InputInfoViewModel.kt │ │ │ │ │ └── InputTimeViewModel.kt │ │ │ ├── othertimesetting │ │ │ │ └── view │ │ │ │ │ └── OtherTimeSettingActivity.kt │ │ │ ├── setting │ │ │ │ └── view │ │ │ │ │ └── SettingFragment.kt │ │ │ ├── splash │ │ │ │ └── SplashActivity.kt │ │ │ ├── todayweather │ │ │ │ ├── adapter │ │ │ │ │ └── TodayWeatherAdapter.kt │ │ │ │ ├── view │ │ │ │ │ └── TodayWeatherFragment.kt │ │ │ │ └── viewmodel │ │ │ │ │ └── TodayWeatherViewModel.kt │ │ │ ├── todayweathercontainer │ │ │ │ ├── OnPageDownClickListener.kt │ │ │ │ ├── adapter │ │ │ │ │ └── TodayWeatherContainerAdapter.kt │ │ │ │ ├── view │ │ │ │ │ └── TodayWeatherContainerFragment.kt │ │ │ │ └── viewmodel │ │ │ │ │ └── TodayWeatherContainerViewModel.kt │ │ │ ├── waketimesetting │ │ │ │ └── view │ │ │ │ │ └── WakeTimeSettingActivity.kt │ │ │ └── weeklyweather │ │ │ │ ├── adapter │ │ │ │ └── WeeklyWeatherAdapter.kt │ │ │ │ ├── view │ │ │ │ └── WeeklyWeatherFragment.kt │ │ │ │ └── viewmodel │ │ │ │ └── WeeklyWeatherViewModel.kt │ │ │ └── util │ │ │ ├── Constants.kt │ │ │ ├── Event.kt │ │ │ ├── EventObserver.kt │ │ │ ├── ItemDiffCallback.kt │ │ │ ├── NestedScrollableHost.kt │ │ │ ├── OnThrottleClickListener.kt │ │ │ ├── ShortWeatherFirebaseMessagingService.kt │ │ │ ├── ShortWeatherSharedPreference.kt │ │ │ ├── binding │ │ │ ├── BindingActivity.kt │ │ │ ├── BindingAdapter.kt │ │ │ └── BindingFragment.kt │ │ │ └── extension │ │ │ ├── ActivityExt.kt │ │ │ ├── ContextExt.kt │ │ │ ├── LiveDataExt.kt │ │ │ └── ViewExt.kt │ └── res │ │ ├── drawable-hdpi │ │ ├── img_clear_day.png │ │ ├── img_clear_night.png │ │ ├── img_cloudy.png │ │ ├── img_lightrain.png │ │ ├── img_lightsnow.png │ │ ├── img_lotcloud_day.png │ │ ├── img_lotcloud_night.png │ │ ├── img_rain.png │ │ ├── img_rainsnow.png │ │ ├── img_shower.png │ │ ├── img_snow.png │ │ └── img_snowdrifting.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ ├── img_clear_day.png │ │ ├── img_clear_night.png │ │ ├── img_cloudy.png │ │ ├── img_lightrain.png │ │ ├── img_lightsnow.png │ │ ├── img_lotcloud_day.png │ │ ├── img_lotcloud_night.png │ │ ├── img_rain.png │ │ ├── img_rainsnow.png │ │ ├── img_shower.png │ │ ├── img_snow.png │ │ └── img_snowdrifting.png │ │ ├── drawable-xxhdpi │ │ ├── img_clear_day.png │ │ ├── img_clear_night.png │ │ ├── img_cloudy.png │ │ ├── img_lightrain.png │ │ ├── img_lightsnow.png │ │ ├── img_lotcloud_day.png │ │ ├── img_lotcloud_night.png │ │ ├── img_rain.png │ │ ├── img_rainsnow.png │ │ ├── img_shower.png │ │ ├── img_snow.png │ │ └── img_snowdrifting.png │ │ ├── drawable-xxxhdpi │ │ ├── img_clear_day.png │ │ ├── img_clear_night.png │ │ ├── img_cloudy.png │ │ ├── img_lightrain.png │ │ ├── img_lightsnow.png │ │ ├── img_lotcloud_day.png │ │ ├── img_lotcloud_night.png │ │ ├── img_rain.png │ │ ├── img_rainsnow.png │ │ ├── img_shower.png │ │ ├── img_snow.png │ │ └── img_snowdrifting.png │ │ ├── drawable │ │ ├── bg_bad_dust.xml │ │ ├── bg_blue_circle.xml │ │ ├── bg_blue_newsflash.xml │ │ ├── bg_bottom_sheet.xml │ │ ├── bg_bottom_sheet_btn_blue.xml │ │ ├── bg_bottom_sheet_btn_gray.xml │ │ ├── bg_cloud.xml │ │ ├── bg_day.xml │ │ ├── bg_fog.xml │ │ ├── bg_good_dust.xml │ │ ├── bg_gray_circle.xml │ │ ├── bg_night.xml │ │ ├── bg_nomal_dust.xml │ │ ├── bg_rain.xml │ │ ├── bg_red_newsflash.xml │ │ ├── bg_snow.xml │ │ ├── bg_today_weather_description.xml │ │ ├── bg_today_weather_sub_description.xml │ │ ├── bg_today_weather_toast.xml │ │ ├── bg_windy.xml │ │ ├── bg_worst_dust.xml │ │ ├── bg_yellow_newsflash.xml │ │ ├── bg_yellowdust.xml │ │ ├── btn_input_info.xml │ │ ├── ic_add.xml │ │ ├── ic_bottom_sheet_drag_view.xml │ │ ├── ic_clear_day.xml │ │ ├── ic_clear_night.xml │ │ ├── ic_clothes.xml │ │ ├── ic_cloudy.xml │ │ ├── ic_dust_bad.xml │ │ ├── ic_dust_good.xml │ │ ├── ic_dust_normal.xml │ │ ├── ic_dust_worst.xml │ │ ├── ic_expand.xml │ │ ├── ic_expand_down.xml │ │ ├── ic_expand_red.xml │ │ ├── ic_expand_right.xml │ │ ├── ic_fog.xml │ │ ├── ic_hail.xml │ │ ├── ic_hamberger.xml │ │ ├── ic_heavyrain.xml │ │ ├── ic_heavysnow.xml │ │ ├── ic_humidity.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_lightning.xml │ │ ├── ic_lightrain.xml │ │ ├── ic_lightsnow.xml │ │ ├── ic_littlecloud_day.xml │ │ ├── ic_littlecloud_night.xml │ │ ├── ic_location.xml │ │ ├── ic_logo.xml │ │ ├── ic_lotcloud_day.xml │ │ ├── ic_lotcloud_night.xml │ │ ├── ic_next_btn.xml │ │ ├── ic_precipitation_1.xml │ │ ├── ic_precipitation_10.xml │ │ ├── ic_precipitation_2.xml │ │ ├── ic_precipitation_3.xml │ │ ├── ic_precipitation_4.xml │ │ ├── ic_precipitation_5.xml │ │ ├── ic_precipitation_6.xml │ │ ├── ic_precipitation_7.xml │ │ ├── ic_precipitation_8.xml │ │ ├── ic_precipitation_9.xml │ │ ├── ic_rain.xml │ │ ├── ic_rainsnow.xml │ │ ├── ic_setting.xml │ │ ├── ic_shower.xml │ │ ├── ic_snow.xml │ │ ├── ic_snowdrifting.xml │ │ ├── ic_sunrise.xml │ │ ├── ic_sunset.xml │ │ ├── ic_toast.xml │ │ ├── ic_today.xml │ │ ├── ic_week.xml │ │ ├── ic_weekly_weather_example.xml │ │ ├── ic_windy.xml │ │ ├── ic_yellowdust.xml │ │ ├── img_clear_day.png │ │ ├── img_clear_night.png │ │ ├── img_cloudy.png │ │ ├── img_lightrain.png │ │ ├── img_lightsnow.png │ │ ├── img_lotcloud_day.png │ │ ├── img_lotcloud_night.png │ │ ├── img_rain.png │ │ ├── img_rainsnow.png │ │ ├── img_shower.png │ │ ├── img_snow.png │ │ ├── img_snowdrifting.png │ │ ├── selector_input_btn_bg.xml │ │ └── selector_input_btn_text_color.xml │ │ ├── font │ │ ├── pretendard_black.otf │ │ ├── pretendard_bold.otf │ │ ├── pretendard_extrabold.otf │ │ ├── pretendard_extralight.otf │ │ ├── pretendard_light.otf │ │ ├── pretendard_medium.otf │ │ ├── pretendard_regular.otf │ │ ├── pretendard_semibold.otf │ │ └── pretendard_thin.otf │ │ ├── layout │ │ ├── activity_alarm_setting.xml │ │ ├── activity_input_info.xml │ │ ├── activity_input_time.xml │ │ ├── activity_main.xml │ │ ├── activity_other_time_setting.xml │ │ ├── activity_splash.xml │ │ ├── activity_wake_time_setting.xml │ │ ├── bottom_sheet_content.xml │ │ ├── bottom_sheet_time_content.xml │ │ ├── fragment_custom_weather.xml │ │ ├── fragment_setting.xml │ │ ├── fragment_today_weather.xml │ │ ├── fragment_today_weather_container.xml │ │ ├── fragment_weekly_weather.xml │ │ ├── item_bottom_sheet.xml │ │ ├── item_custom_weather_precipitation.xml │ │ ├── item_custom_weather_weather.xml │ │ ├── item_drawer_header.xml │ │ ├── item_today_weather_fine_dust.xml │ │ ├── item_today_weather_newsflash.xml │ │ ├── item_today_weather_ultrafine_dust.xml │ │ └── item_weekly_weather.xml │ │ ├── menu │ │ ├── menu_drawer.xml │ │ └── menu_tool_bar.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_round.webp │ │ └── ic_short_weather.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_round.webp │ │ └── ic_short_weather.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_round.webp │ │ └── ic_short_weather.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_round.webp │ │ └── ic_short_weather.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_round.webp │ │ └── ic_short_weather.png │ │ ├── raw │ │ └── shortweather_final.json │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── org │ └── shortweather │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.github/ISSUE_TEMPLATE/issue_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ISSUE_TEMPLATE 3 | about: "숏웨더 기본 이슈 템플릿입니다." 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Issue 📌 11 | 12 | ## Todo 📝 13 | - [ ] 14 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Issue 📌 2 | 3 | ## Description ✏ 4 | - 5 | 6 | ## **ScreenShot ✨** 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🌩 숏웨더 🌩 2 | ### 어제의 날씨로 알아보는 오늘의 날씨 3 | 4 |
5 | 6 | ## Contributors 🌥 7 | | [@SunwoongH](https://github.com/SunwoongH) | [@chaso1495](https://github.com/chaso1495) | [@ahra1221](https://github.com/ahra1221) | 8 | | :---: | :---: | :---: | 9 | |||| 10 | |**오늘 날씨 & 맞춤 날씨 뷰**|**정보 입력 & 스플래쉬 & 설정 뷰**|**주간 날씨 & 설정 뷰**| 11 | 12 |
13 | 14 | ![main](https://user-images.githubusercontent.com/81796317/212494861-8ce6e41a-52db-45e3-8f6a-0ab8865c5678.jpg) 15 | 16 | ## Android Coding Convention 🌦 17 | [android coding convention 📝](https://devjoy.notion.site/Android-Coding-Convention-2d1428b408614047a1fafa698383d4e0) 18 | 19 |
20 | 21 | ## Git Convention 🌨 22 | [git convention 📝](https://devjoy.notion.site/Git-Convention-bab184da78c548f085b02026bbb86cbe) 23 | 24 |
25 | 26 | ## Teck Stack ⛈ 27 | 28 | | Architecture | Clean Architecture, MVVM | 29 | |:---|:---| 30 | | Design Pattern | Repository Pattern, Adapter Pattern, Delegation Pattern, Observer Pattern | 31 | | Jetpack Components | LiveData, Lifecycle, ViewModel, DataBinding | 32 | | Dependency Injection | Hilt | 33 | | Network | Retrofit, OkHttp | 34 | | Asynchronous Processing | Coroutine | 35 | | Third Party Library | Lottie, kotlinSerialization, Firebase | 36 | | Strategy | Git Flow | 37 | | Other Tool | Slack, Notion, Figma, Postman | 38 | 39 |
40 | 41 | ## 시연 영상 ⛅ 42 | 43 | 44 |
45 | 46 | ## Foldering 🌩 47 | ``` 48 | 📂 org.shortweather 49 | ┣ 📂 data 50 | ┃ ┣ 📂 api 51 | ┃ ┣ 📂 model 52 | ┃ ┣ 📂 repository 53 | ┃ ┣ 📂 source 54 | ┃ ┣ 📂 local 55 | ┃ ┣ 📂 remote 56 | ┣ 📂 di 57 | ┣ 📂 domain 58 | ┃ ┣ 📂 repository 59 | ┣ 📂 presentation 60 | ┃ ┣ 📂 alarmsetting 61 | ┃ ┣ 📂 customweather 62 | ┃ ┣ 📂 input 63 | ┃ ┣ 📂 othertimesetting 64 | ┃ ┣ 📂 setting 65 | ┃ ┣ 📂 splash 66 | ┃ ┣ 📂 todayweather 67 | ┃ ┣ 📂 todayweathercontainer 68 | ┃ ┣ 📂 adapter 69 | ┃ ┣ 📂 view 70 | ┃ ┣ 📂 viewmodel 71 | ┃ ┣ 📂 waketimesetting 72 | ┃ ┣ 📂 weeklyweather 73 | ┣ 📂 util 74 | ┃ ┣ 📂 binding 75 | ┃ ┣ 📂 extension 76 | ``` 77 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/org/shortweather/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("org.shortweather", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 19 | 23 | 27 | 31 | 35 | 39 | 43 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/ShortWeatherApplication.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather 2 | 3 | import android.app.Application 4 | import android.content.SharedPreferences 5 | import com.google.firebase.messaging.FirebaseMessaging 6 | import dagger.hilt.android.HiltAndroidApp 7 | import org.shortweather.util.ShortWeatherSharedPreference 8 | 9 | 10 | @HiltAndroidApp 11 | class ShortWeatherApplication : Application(){ 12 | override fun onCreate() { 13 | super.onCreate() 14 | ShortWeatherSharedPreference.setDeviceToken(this) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/api/AuthService.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.api 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.RequestUserInfo 5 | import org.shortweather.data.model.ResponseUserCheck 6 | import org.shortweather.data.model.ResponseUserInfo 7 | import retrofit2.http.* 8 | 9 | interface AuthService { 10 | /** 11 | * 유저 정보 입력 API 12 | */ 13 | @POST("auth") 14 | suspend fun createUser( 15 | @Body requestUserInfo: RequestUserInfo 16 | ): BaseResponse 17 | 18 | /** 19 | * 유저 등록 조회 API 20 | */ 21 | @GET("auth/login") 22 | suspend fun searchUser( 23 | @Header("deviceToken") deviceToken: String 24 | ): BaseResponse 25 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/api/CustomWeatherService.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.api 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.ResponseCustomWeatherDetail 5 | import org.shortweather.data.model.ResponseCustomWeatherRain 6 | import org.shortweather.data.model.ResponseCustomWeatherTemp 7 | import retrofit2.http.GET 8 | import retrofit2.http.Header 9 | 10 | interface CustomWeatherService { 11 | /** 12 | * 오늘 날씨 정보 조회 API 13 | */ 14 | @GET("/weather/today/detail") 15 | suspend fun getDetail( 16 | @Header("Authorization") accessToken: String 17 | ): BaseResponse 18 | 19 | /** 20 | * 시간대별 날씨 화면 날씨 조회 API 21 | */ 22 | @GET("weather/today/detail/temp") 23 | suspend fun getTemp(): BaseResponse> 24 | 25 | /** 26 | * 시간대별 날씨 화면 강수 조회 API 27 | */ 28 | @GET("weather/today/detail/rain") 29 | suspend fun getRain(): BaseResponse> 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/api/TodayWeatherService.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.api 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.ResponseTodayWeatherInfo 5 | import org.shortweather.data.model.ResponseTodayWeatherToastInfo 6 | import retrofit2.http.GET 7 | import retrofit2.http.Header 8 | 9 | interface TodayWeatherService { 10 | /** 11 | * 오늘 날씨 조회 API 12 | */ 13 | @GET("weather/today") 14 | suspend fun getTodayWeatherInfo( 15 | @Header("Authorization") accessToken: String 16 | ): BaseResponse 17 | 18 | /** 19 | * 오늘 날씨 toast 조회 API 20 | */ 21 | @GET("weather/today/question") 22 | suspend fun getTodayWeatherToastInfo( 23 | @Header("Authorization") accessToken: String 24 | ): BaseResponse 25 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/model/BaseResponse.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class BaseResponse( 7 | val status: Int, 8 | val success: Boolean, 9 | val message: String, 10 | val data: T? = null 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/model/CustomWeather.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class ResponseCustomWeatherDetail( 7 | val location: String, 8 | val goOut: ResponseGoOut, 9 | val goHome: ResponseGoHome, 10 | val todayWeather: ResponseTodayWeather 11 | ) { 12 | @Serializable 13 | data class ResponseGoOut( 14 | val time: String, 15 | val temp : Int, 16 | val day: Boolean, 17 | val image: String 18 | ) 19 | 20 | @Serializable 21 | data class ResponseGoHome( 22 | val time: String, 23 | val temp: Int, 24 | val day: Boolean, 25 | val image: String 26 | ) 27 | 28 | @Serializable 29 | data class ResponseTodayWeather( 30 | val humidity: Int, 31 | val sunrise: String, 32 | val sunset: String, 33 | val fineDust: Int, 34 | val ultraFineDust: Int 35 | ) 36 | } 37 | 38 | @Serializable 39 | data class ResponseCustomWeatherTemp( 40 | val date: String, 41 | val time: String, 42 | val temperature: Int, 43 | val day: Boolean, 44 | val image: String 45 | ) 46 | 47 | data class CustomWeatherTemp( 48 | val data: ResponseCustomWeatherTemp, 49 | val isCurrent: Boolean = false 50 | ) 51 | 52 | @Serializable 53 | data class ResponseCustomWeatherRain( 54 | val date: String, 55 | val time: String, 56 | val rain: Int 57 | ) 58 | 59 | data class CustomWeatherPrecipitation( 60 | val data: ResponseCustomWeatherRain, 61 | val isCurrent: Boolean = false 62 | ) -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/model/SettingTimeData.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class RequestOtherTime( 7 | val goOutTime: String, 8 | val goHomeTime: String 9 | ) 10 | 11 | @Serializable 12 | data class ResponseOtherTime( 13 | val id: Int, 14 | val goOutTime: String, 15 | val goHomeTime: String 16 | ) 17 | 18 | @Serializable 19 | data class RequestWakeTime( 20 | val wakeUpTime: String 21 | ) 22 | 23 | @Serializable 24 | data class ResponseWakeTime( 25 | val id: Int, 26 | val wakeUpTime: String 27 | ) 28 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/model/TodayWeather.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | sealed class TodayWeatherTag 6 | 7 | data class Newsflash( 8 | val description: String 9 | ) : TodayWeatherTag() 10 | 11 | data class FineDust( 12 | val fineDustLevel: Int 13 | ) : TodayWeatherTag() 14 | 15 | data class UltrafineDust( 16 | val ultrafineDustLevel: Int 17 | ) : TodayWeatherTag() 18 | 19 | @Serializable 20 | data class ResponseTodayWeatherInfo( 21 | val location: String, 22 | val compareTemp: Int, 23 | val compareMessage: String, 24 | val breakingNews: String?, 25 | val fineDust: Int, 26 | val ultrafineDust: Int, 27 | val day: Boolean, 28 | val image: String, 29 | val currentTemp: Int, 30 | val minTemp: Int, 31 | val maxTemp: Int, 32 | val weatherMessage: String 33 | ) 34 | 35 | @Serializable 36 | data class ResponseTodayWeatherToastInfo( 37 | val temp: Int, 38 | val weatherMessage: String 39 | ) -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/model/UserData.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | // 유저 등록 조회 Request -> Header로 바로 처리 6 | 7 | // 유저 등록 조회 Response 8 | @Serializable 9 | data class ResponseUserCheck( 10 | val deviceToken: String, 11 | val accessToken: String?, 12 | val isExist: Boolean 13 | ) 14 | 15 | // 유저 정보 입력 Request 16 | @Serializable 17 | data class RequestUserInfo( 18 | val gender: String, 19 | val age: String, 20 | val tempSens: String, 21 | val wakeUpTime: String, 22 | val goOutTime: String, 23 | val goHomeTime: String, 24 | val deviceToken: String, 25 | ) 26 | 27 | // 유저 정보 입력 Response 28 | @Serializable 29 | data class ResponseUserInfo( 30 | val id: Int, 31 | val gender: String, 32 | val age: String, 33 | val tempSens: String, 34 | val wakeUpTime: String, 35 | val goOutTime: String, 36 | val goHomeTime: String, 37 | val deviceToken: String, 38 | val accessToken: String 39 | ) 40 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/model/WeeklyWeather.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class WeeklyWeather( 7 | val day: String, 8 | val date: String, 9 | val dayImage: String, 10 | val dayRain: Int, 11 | val nightImage: String, 12 | val nightRain: Int, 13 | val isDay: Boolean, 14 | val minTemp: Int, 15 | val maxTemp: Int 16 | ) -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/repository/AuthRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.repository 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.RequestUserInfo 5 | import org.shortweather.data.model.ResponseUserCheck 6 | import org.shortweather.data.model.ResponseUserInfo 7 | import org.shortweather.data.source.remote.AuthRemoteDataSource 8 | import org.shortweather.domain.repository.AuthRepository 9 | import javax.inject.Inject 10 | 11 | class AuthRepositoryImpl @Inject constructor(private val authRemoteDataSource: AuthRemoteDataSource) : 12 | AuthRepository { 13 | override suspend fun searchUser(deviceToken: String): BaseResponse = 14 | authRemoteDataSource.searchUser(deviceToken) 15 | 16 | override suspend fun createUser(requestUserInfo: RequestUserInfo): BaseResponse = 17 | authRemoteDataSource.createUser(requestUserInfo) 18 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/repository/CustomWeatherRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.repository 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.ResponseCustomWeatherDetail 5 | import org.shortweather.data.model.ResponseCustomWeatherRain 6 | import org.shortweather.data.model.ResponseCustomWeatherTemp 7 | import org.shortweather.data.source.remote.CustomWeatherRemoteDataSource 8 | import org.shortweather.domain.repository.CustomWeatherRepository 9 | import javax.inject.Inject 10 | 11 | class CustomWeatherRepositoryImpl @Inject constructor( 12 | private val customWeatherDataSource: CustomWeatherRemoteDataSource 13 | ) : CustomWeatherRepository { 14 | override suspend fun getDetail(accessToken: String): BaseResponse = 15 | customWeatherDataSource.getDetail(accessToken) 16 | 17 | override suspend fun getTemp(): BaseResponse> = 18 | customWeatherDataSource.getTemp() 19 | 20 | override suspend fun getRain(): BaseResponse> = 21 | customWeatherDataSource.getRain() 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/repository/TodayWeatherRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.repository 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.ResponseTodayWeatherInfo 5 | import org.shortweather.data.model.ResponseTodayWeatherToastInfo 6 | import org.shortweather.data.source.remote.TodayWeatherRemoteDataSource 7 | import org.shortweather.domain.repository.TodayWeatherRepository 8 | import javax.inject.Inject 9 | 10 | class TodayWeatherRepositoryImpl @Inject constructor( 11 | private val todayWeatherRemoteDataSource: TodayWeatherRemoteDataSource 12 | ) : TodayWeatherRepository { 13 | override suspend fun getTodayWeatherInfo(accessToken: String): BaseResponse = 14 | todayWeatherRemoteDataSource.getTodayWeatherInfo(accessToken) 15 | 16 | override suspend fun getTodayWeatherToastInfo(accessToken: String): BaseResponse = 17 | todayWeatherRemoteDataSource.getTodayWeatherToastInfo(accessToken) 18 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/source/remote/AuthRemoteDataSource.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.source.remote 2 | 3 | import org.shortweather.data.api.AuthService 4 | import org.shortweather.data.model.BaseResponse 5 | import org.shortweather.data.model.RequestUserInfo 6 | import org.shortweather.data.model.ResponseUserCheck 7 | import org.shortweather.data.model.ResponseUserInfo 8 | import javax.inject.Inject 9 | 10 | class AuthRemoteDataSource @Inject constructor( 11 | private val authservice: AuthService 12 | ) { 13 | suspend fun createUser(requestUserInfo: RequestUserInfo): BaseResponse = 14 | authservice.createUser(requestUserInfo) 15 | 16 | suspend fun searchUser(deviceToken: String): BaseResponse = 17 | authservice.searchUser(deviceToken) 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/source/remote/CustomWeatherRemoteDataSource.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.source.remote 2 | 3 | import org.shortweather.data.api.CustomWeatherService 4 | import org.shortweather.data.model.BaseResponse 5 | import org.shortweather.data.model.ResponseCustomWeatherDetail 6 | import org.shortweather.data.model.ResponseCustomWeatherRain 7 | import org.shortweather.data.model.ResponseCustomWeatherTemp 8 | import javax.inject.Inject 9 | 10 | class CustomWeatherRemoteDataSource @Inject constructor( 11 | private val customWeatherService: CustomWeatherService 12 | ) { 13 | suspend fun getDetail(accessToken: String): 14 | BaseResponse = customWeatherService.getDetail(accessToken) 15 | 16 | suspend fun getTemp(): 17 | BaseResponse> = customWeatherService.getTemp() 18 | 19 | suspend fun getRain(): 20 | BaseResponse> = customWeatherService.getRain() 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/data/source/remote/TodayWeatherRemoteDataSource.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.data.source.remote 2 | 3 | import org.shortweather.data.api.TodayWeatherService 4 | import org.shortweather.data.model.BaseResponse 5 | import org.shortweather.data.model.ResponseTodayWeatherInfo 6 | import org.shortweather.data.model.ResponseTodayWeatherToastInfo 7 | import javax.inject.Inject 8 | 9 | class TodayWeatherRemoteDataSource @Inject constructor( 10 | private val todayWeatherService: TodayWeatherService 11 | ) { 12 | suspend fun getTodayWeatherInfo(accessToken: String): BaseResponse = 13 | todayWeatherService.getTodayWeatherInfo(accessToken) 14 | 15 | suspend fun getTodayWeatherToastInfo(accessToken: String): BaseResponse = 16 | todayWeatherService.getTodayWeatherToastInfo(accessToken) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/di/NetworkModule.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.di 2 | 3 | import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory 4 | import dagger.Module 5 | import dagger.Provides 6 | import dagger.hilt.InstallIn 7 | import dagger.hilt.components.SingletonComponent 8 | import kotlinx.serialization.ExperimentalSerializationApi 9 | import kotlinx.serialization.json.Json 10 | import okhttp3.MediaType.Companion.toMediaType 11 | import okhttp3.OkHttpClient 12 | import okhttp3.logging.HttpLoggingInterceptor 13 | import org.shortweather.BuildConfig.BASE_URL 14 | import retrofit2.Retrofit 15 | import java.util.concurrent.TimeUnit 16 | import javax.inject.Qualifier 17 | import javax.inject.Singleton 18 | 19 | @Module 20 | @InstallIn(SingletonComponent::class) 21 | object NetworkModule { 22 | @Provides 23 | @Singleton 24 | fun providesHttpLoggingInterceptor(): HttpLoggingInterceptor = HttpLoggingInterceptor().apply { 25 | level = HttpLoggingInterceptor.Level.BODY 26 | } 27 | 28 | @Provides 29 | @Singleton 30 | fun providesOkHttpClient(httpLoggingInterceptor: HttpLoggingInterceptor): OkHttpClient = 31 | OkHttpClient.Builder() 32 | .connectTimeout(10, TimeUnit.SECONDS) 33 | .writeTimeout(10, TimeUnit.SECONDS) 34 | .readTimeout(10, TimeUnit.SECONDS) 35 | .addInterceptor(httpLoggingInterceptor) 36 | .build() 37 | 38 | @Provides 39 | @Singleton 40 | @ExperimentalSerializationApi 41 | fun providesRetrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder() 42 | .baseUrl(BASE_URL) 43 | .client(okHttpClient) 44 | .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) 45 | .build() 46 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/di/RepositoryModule.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.di 2 | 3 | import dagger.Binds 4 | import dagger.Module 5 | import dagger.hilt.InstallIn 6 | import dagger.hilt.components.SingletonComponent 7 | import org.shortweather.data.repository.AuthRepositoryImpl 8 | import org.shortweather.data.repository.CustomWeatherRepositoryImpl 9 | import org.shortweather.data.repository.TodayWeatherRepositoryImpl 10 | import org.shortweather.domain.repository.AuthRepository 11 | import org.shortweather.domain.repository.CustomWeatherRepository 12 | import org.shortweather.domain.repository.TodayWeatherRepository 13 | import javax.inject.Singleton 14 | 15 | @Module 16 | @InstallIn(SingletonComponent::class) 17 | abstract class RepositoryModule { 18 | @Binds 19 | @Singleton 20 | abstract fun bindsAuthRepository(authRepositoryImpl: AuthRepositoryImpl): AuthRepository 21 | 22 | @Binds 23 | @Singleton 24 | abstract fun bindsTodayWeatherRepository(todayWeatherRepositoryImpl: TodayWeatherRepositoryImpl): TodayWeatherRepository 25 | 26 | @Binds 27 | @Singleton 28 | abstract fun bindsWeatherRepository(customWeatherRepository: CustomWeatherRepositoryImpl): CustomWeatherRepository 29 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/di/ServiceModule.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.di 2 | 3 | import dagger.Module 4 | import dagger.Provides 5 | import dagger.hilt.InstallIn 6 | import dagger.hilt.components.SingletonComponent 7 | import org.shortweather.data.api.AuthService 8 | import org.shortweather.data.api.CustomWeatherService 9 | import org.shortweather.data.api.TodayWeatherService 10 | import retrofit2.Retrofit 11 | import javax.inject.Singleton 12 | 13 | @Module 14 | @InstallIn(SingletonComponent::class) 15 | object ServiceModule { 16 | @Provides 17 | @Singleton 18 | fun providesAuthService(retrofit: Retrofit): AuthService = 19 | retrofit.create(AuthService::class.java) 20 | 21 | @Provides 22 | @Singleton 23 | fun providesTodayWeatherService(retrofit: Retrofit): TodayWeatherService = 24 | retrofit.create(TodayWeatherService::class.java) 25 | 26 | @Provides 27 | @Singleton 28 | fun providesCustomWeatherService(retrofit: Retrofit): CustomWeatherService = 29 | retrofit.create(CustomWeatherService::class.java) 30 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/domain/repository/AuthRepository.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.domain.repository 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.RequestUserInfo 5 | import org.shortweather.data.model.ResponseUserCheck 6 | import org.shortweather.data.model.ResponseUserInfo 7 | 8 | interface AuthRepository { 9 | suspend fun createUser(requestUserInfo: RequestUserInfo): BaseResponse 10 | suspend fun searchUser(deviceToken: String): BaseResponse 11 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/domain/repository/CustomWeatherRepository.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.domain.repository 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.ResponseCustomWeatherDetail 5 | import org.shortweather.data.model.ResponseCustomWeatherRain 6 | import org.shortweather.data.model.ResponseCustomWeatherTemp 7 | 8 | interface CustomWeatherRepository { 9 | suspend fun getDetail(accessToken: String): BaseResponse 10 | suspend fun getTemp(): BaseResponse> 11 | suspend fun getRain(): BaseResponse> 12 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/domain/repository/TodayWeatherRepository.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.domain.repository 2 | 3 | import org.shortweather.data.model.BaseResponse 4 | import org.shortweather.data.model.ResponseTodayWeatherInfo 5 | import org.shortweather.data.model.ResponseTodayWeatherToastInfo 6 | 7 | interface TodayWeatherRepository { 8 | suspend fun getTodayWeatherInfo(accessToken: String): BaseResponse 9 | suspend fun getTodayWeatherToastInfo(accessToken: String): BaseResponse 10 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation 2 | 3 | import android.os.Bundle 4 | import androidx.activity.viewModels 5 | import androidx.fragment.app.Fragment 6 | import dagger.hilt.android.AndroidEntryPoint 7 | import org.shortweather.R 8 | import org.shortweather.databinding.ActivityMainBinding 9 | import org.shortweather.presentation.setting.view.SettingFragment 10 | import org.shortweather.presentation.todayweathercontainer.view.TodayWeatherContainerFragment 11 | import org.shortweather.presentation.weeklyweather.view.WeeklyWeatherFragment 12 | import org.shortweather.util.binding.BindingActivity 13 | import org.shortweather.util.extension.replace 14 | 15 | @AndroidEntryPoint 16 | class MainActivity : BindingActivity(R.layout.activity_main) { 17 | private val viewModel: MainViewModel by viewModels() 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | 21 | binding.viewModel = viewModel 22 | binding.lifecycleOwner = this 23 | initView() 24 | setNavigationItemSelectedListener() 25 | setNavigation() 26 | startTargetFragment(R.id.today_weather_menu_drawer) 27 | } 28 | 29 | private fun setTitle(text: String) { 30 | viewModel.setTitle(text) 31 | } 32 | 33 | private fun setIsSetting(setting: Boolean) { 34 | viewModel.setIsSetting(setting) 35 | } 36 | 37 | private fun initView() { 38 | binding.nvMain.itemIconTintList = null 39 | startTargetFragment(TodayWeatherContainerFragment()) 40 | } 41 | 42 | private fun setNavigationItemSelectedListener() { 43 | binding.nvMain.setNavigationItemSelectedListener { menuItem -> 44 | startTargetFragment(menuItem.itemId) 45 | binding.dlMain.close() 46 | true 47 | } 48 | } 49 | 50 | private fun setNavigation() { 51 | binding.tbMain.setNavigationOnClickListener { 52 | binding.dlMain.open() 53 | } 54 | } 55 | 56 | private fun startTargetFragment(fragment: Fragment) { 57 | supportFragmentManager.beginTransaction() 58 | .replace(R.id.fcv_main, fragment) 59 | .commitAllowingStateLoss() 60 | } 61 | 62 | private fun startTargetFragment(itemId: Int) = when (itemId) { 63 | R.id.today_weather_menu_drawer -> { 64 | replace(R.id.fcv_main) 65 | setTitle(getString(R.string.title_today_weather)) 66 | setIsSetting(true) 67 | } 68 | R.id.weekly_weather_menu_drawer -> { 69 | replace(R.id.fcv_main) 70 | setTitle(getString(R.string.title_weekly_weather)) 71 | setIsSetting(true) 72 | } 73 | R.id.clothes_menu_drawer -> {} 74 | R.id.setting_menu_drawer -> { 75 | replace(R.id.fcv_main) 76 | setTitle(getString(R.string.title_setting)) 77 | setIsSetting(false) 78 | } 79 | else -> throw IllegalArgumentException("Not found error.") 80 | } 81 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | import dagger.hilt.android.lifecycle.HiltViewModel 7 | import javax.inject.Inject 8 | 9 | @HiltViewModel 10 | class MainViewModel @Inject constructor() : ViewModel() { 11 | private val _title = MutableLiveData() 12 | val title: LiveData 13 | get() = _title 14 | 15 | private val _isSetting = MutableLiveData(false) 16 | val isSetting: LiveData 17 | get() = _isSetting 18 | 19 | fun setTitle(text: String) { 20 | _title.value = text 21 | } 22 | 23 | fun setIsSetting(setting: Boolean) { 24 | _isSetting.value = setting 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/alarmsetting/view/AlarmSettingActivity.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.alarmsetting.view 2 | 3 | import android.os.Bundle 4 | import androidx.activity.viewModels 5 | import dagger.hilt.EntryPoint 6 | import dagger.hilt.android.AndroidEntryPoint 7 | import org.shortweather.R 8 | import org.shortweather.databinding.ActivityAlarmSettingBinding 9 | import org.shortweather.presentation.alarmsetting.viewmodel.AlarmSettingViewModel 10 | import org.shortweather.util.binding.BindingActivity 11 | 12 | @AndroidEntryPoint 13 | class AlarmSettingActivity : 14 | BindingActivity(R.layout.activity_alarm_setting) { 15 | private val viewModel by viewModels() 16 | 17 | override fun onCreate(savedInstanceState: Bundle?) { 18 | super.onCreate(savedInstanceState) 19 | 20 | binding.viewModel = viewModel 21 | binding.lifecycleOwner = this 22 | initView() 23 | setOnCheckedChangeListener() 24 | } 25 | 26 | private fun initView(){ 27 | binding.btnAlarmSettingAll.isChecked = true 28 | binding.btnAlarmSettingWake.isChecked = true 29 | } 30 | 31 | private fun setOnCheckedChangeListener() { 32 | binding.btnAlarmSettingAll.setOnCheckedChangeListener { _, isChecked -> 33 | if (isChecked) { 34 | viewModel.setIsChange(true) 35 | } else { 36 | viewModel.setIsChange(false) 37 | } 38 | } 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/alarmsetting/viewmodel/AlarmSettingViewModel.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.alarmsetting.viewmodel 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import dagger.hilt.android.HiltAndroidApp 6 | import dagger.hilt.android.lifecycle.HiltViewModel 7 | import javax.inject.Inject 8 | 9 | @HiltViewModel 10 | class AlarmSettingViewModel @Inject constructor(): ViewModel() { 11 | val isChange = MutableLiveData(true) 12 | 13 | fun setIsChange(select: Boolean) { 14 | isChange.value = select 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/customweather/adapter/CustomWeatherPrecipitationAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.customweather.adapter 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.ListAdapter 6 | import androidx.recyclerview.widget.RecyclerView 7 | import org.shortweather.data.model.CustomWeatherPrecipitation 8 | import org.shortweather.databinding.ItemCustomWeatherPrecipitationBinding 9 | import org.shortweather.util.ItemDiffCallback 10 | 11 | class CustomWeatherPrecipitationAdapter : 12 | ListAdapter( 13 | ItemDiffCallback( 14 | onContentsTheSame = { oldItem, newItem -> oldItem == newItem }, 15 | onItemsTheSame = { oldItem, newItem -> oldItem == newItem }) 16 | ) { 17 | private lateinit var inflater: LayoutInflater 18 | 19 | override fun onCreateViewHolder( 20 | parent: ViewGroup, 21 | viewType: Int 22 | ): CustomWeatherPrecipitationViewHolder { 23 | if (!::inflater.isInitialized) { 24 | inflater = LayoutInflater.from(parent.context) 25 | } 26 | return CustomWeatherPrecipitationViewHolder( 27 | ItemCustomWeatherPrecipitationBinding.inflate( 28 | inflater, 29 | parent, 30 | false 31 | ) 32 | ) 33 | } 34 | 35 | override fun onBindViewHolder(holder: CustomWeatherPrecipitationViewHolder, position: Int) { 36 | holder.onBind(currentList[position]) 37 | } 38 | 39 | class CustomWeatherPrecipitationViewHolder( 40 | private val binding: ItemCustomWeatherPrecipitationBinding 41 | ) : RecyclerView.ViewHolder(binding.root) { 42 | fun onBind(customWeatherPrecipitation: CustomWeatherPrecipitation) { 43 | binding.customWeatherPrecipitation = customWeatherPrecipitation 44 | binding.executePendingBindings() 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/customweather/adapter/CustomWeatherTempAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.customweather.adapter 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.ListAdapter 6 | import androidx.recyclerview.widget.RecyclerView 7 | import org.shortweather.data.model.CustomWeatherTemp 8 | import org.shortweather.databinding.ItemCustomWeatherWeatherBinding 9 | import org.shortweather.util.ItemDiffCallback 10 | 11 | class CustomWeatherTempAdapter : 12 | ListAdapter( 13 | ItemDiffCallback( 14 | onContentsTheSame = { oldItem, newItem -> oldItem == newItem }, 15 | onItemsTheSame = { oldItem, newItem -> oldItem == newItem }) 16 | ) { 17 | private lateinit var inflater: LayoutInflater 18 | 19 | override fun onCreateViewHolder( 20 | parent: ViewGroup, 21 | viewType: Int 22 | ): CustomWeatherTempViewHolder { 23 | if (!::inflater.isInitialized) { 24 | inflater = LayoutInflater.from(parent.context) 25 | } 26 | return CustomWeatherTempViewHolder( 27 | ItemCustomWeatherWeatherBinding.inflate( 28 | inflater, 29 | parent, 30 | false 31 | ) 32 | ) 33 | } 34 | 35 | override fun onBindViewHolder(holder: CustomWeatherTempViewHolder, position: Int) { 36 | holder.onBind(currentList[position]) 37 | } 38 | 39 | class CustomWeatherTempViewHolder( 40 | private val binding: ItemCustomWeatherWeatherBinding 41 | ) : RecyclerView.ViewHolder(binding.root) { 42 | fun onBind(responseTemp: CustomWeatherTemp) { 43 | binding.customWeatherTemp = responseTemp 44 | binding.executePendingBindings() 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/input/adapter/BottomSheetAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.input.adapter 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.core.app.NotificationCompat.getColor 6 | import androidx.recyclerview.widget.RecyclerView 7 | import org.shortweather.R 8 | import org.shortweather.databinding.ItemBottomSheetBinding 9 | 10 | class BottomSheetAdapter( 11 | private val list: MutableList, 12 | private val listener: OnItemClickListener 13 | ) : RecyclerView.Adapter() { 14 | private var itemList: MutableList = list 15 | private lateinit var inflater: LayoutInflater 16 | 17 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InfoItemHolder { 18 | if (!::inflater.isInitialized) { 19 | inflater = LayoutInflater.from(parent.context) 20 | } 21 | return InfoItemHolder(ItemBottomSheetBinding.inflate(inflater, parent, false)) 22 | } 23 | 24 | override fun onBindViewHolder(holder: InfoItemHolder, position: Int) { 25 | val item = itemList[position] 26 | holder.onBind(item) 27 | } 28 | 29 | override fun getItemCount(): Int = itemList.size 30 | 31 | inner class InfoItemHolder( 32 | private val binding: ItemBottomSheetBinding 33 | ) : RecyclerView.ViewHolder(binding.root) { 34 | fun onBind(item: BottomSheetItem) { 35 | binding.root.setOnClickListener { 36 | listener.onItemClick(item) 37 | } 38 | binding.tvContents.text = item.contents 39 | } 40 | } 41 | 42 | interface OnItemClickListener { 43 | fun onItemClick(item: BottomSheetItem) 44 | } 45 | } 46 | 47 | data class BottomSheetItem(var contents: String) // 선택할 아이템 -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/input/viewmodel/InputInfoViewModel.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.input.viewmodel 2 | 3 | import androidx.lifecycle.* 4 | import dagger.hilt.android.lifecycle.HiltViewModel 5 | import javax.inject.Inject 6 | 7 | @HiltViewModel 8 | class InputInfoViewModel @Inject constructor() : ViewModel() { 9 | 10 | val inputGender = MutableLiveData(" ") // 최초상태를 의미하는 하나의 공백 삽입 11 | val inputAge = MutableLiveData(" ") 12 | val inputSense = MutableLiveData(" ") 13 | val isGenderSelected: LiveData = // 빈칸인지 아닌지 확인하여 아이템 선택이 취소되었는지 관찰하기 위함 14 | Transformations.map(inputGender) { it -> 15 | it.isNotEmpty() 16 | } 17 | val isAgeSelected: LiveData = Transformations.map(inputAge) { it -> 18 | it.isNotEmpty() 19 | } 20 | val isSenseSelected: LiveData = Transformations.map(inputSense) { it -> 21 | it.isNotEmpty() 22 | } 23 | val isGenderSuccess: LiveData = // "한칸 공백도 아니고 빈칸도 아님 -> 아이템 선택 성공" 여부를 관찰하기 위함 24 | Transformations.map(inputGender) { it -> 25 | !(it.equals(" ") || it.equals("")) 26 | } 27 | val isAgeSuccess: LiveData = Transformations.map(inputAge) { it -> 28 | !(it.equals(" ") || it.equals("")) 29 | } 30 | val isSenseSuccess: LiveData = Transformations.map(inputSense) { it -> 31 | !(it.equals(" ") || it.equals("")) 32 | } 33 | 34 | fun getGender(): String { // getter 35 | return inputGender.value!! 36 | } 37 | 38 | fun setGender(gender: String) { // setter 39 | inputGender.value = gender 40 | } 41 | 42 | fun getAge(): String { 43 | return inputAge.value!! 44 | } 45 | 46 | fun setAge(age: String) { 47 | inputAge.value = age 48 | } 49 | 50 | fun getSense(): String { 51 | return inputSense.value!! 52 | } 53 | 54 | fun setSense(sense: String) { 55 | inputSense.value = sense 56 | } 57 | 58 | fun checkAllInputFiled(): Boolean { // 모든 정보가 입력되면 다음 버튼을 활성화시키기 위한 함수 59 | return (isGenderSuccess.value!! && isAgeSuccess.value!! && isSenseSuccess.value!!) 60 | } 61 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/setting/view/SettingFragment.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.setting.view 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.view.View 6 | import org.shortweather.R 7 | import org.shortweather.databinding.FragmentSettingBinding 8 | import org.shortweather.presentation.alarmsetting.view.AlarmSettingActivity 9 | import org.shortweather.presentation.othertimesetting.view.OtherTimeSettingActivity 10 | import org.shortweather.presentation.waketimesetting.view.WakeTimeSettingActivity 11 | import org.shortweather.util.binding.BindingFragment 12 | 13 | class SettingFragment : 14 | BindingFragment(R.layout.fragment_setting) { 15 | 16 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 17 | super.onViewCreated(view, savedInstanceState) 18 | 19 | setOnClickListener() 20 | } 21 | 22 | fun setOnClickListener() { 23 | binding.layoutSettingTime.setOnClickListener { 24 | val intent = Intent(context, OtherTimeSettingActivity::class.java) 25 | startActivity(intent) 26 | } 27 | binding.layoutSettingAlarm.setOnClickListener { 28 | val intent = Intent(context, AlarmSettingActivity::class.java) 29 | startActivity(intent) 30 | } 31 | binding.layoutSettingWakeUp.setOnClickListener { 32 | val intent = Intent(context, WakeTimeSettingActivity::class.java) 33 | startActivity(intent) 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/splash/SplashActivity.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.splash 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.os.Handler 6 | import android.os.Looper 7 | import androidx.activity.viewModels 8 | import dagger.hilt.android.AndroidEntryPoint 9 | import org.shortweather.R 10 | import org.shortweather.databinding.ActivitySplashBinding 11 | import org.shortweather.presentation.MainActivity 12 | import org.shortweather.presentation.input.view.InputInfoActivity 13 | import org.shortweather.presentation.input.viewmodel.InputTimeViewModel 14 | import org.shortweather.util.Constants.SUCCESS_200 15 | import org.shortweather.util.Constants.FAILURE 16 | import org.shortweather.util.Constants.HTTP_EXCEPTION_400 17 | import org.shortweather.util.Constants.HTTP_EXCEPTION_401 18 | import org.shortweather.util.Constants.HTTP_EXCEPTION_500 19 | import org.shortweather.util.EventObserver 20 | import org.shortweather.util.ShortWeatherSharedPreference 21 | import org.shortweather.util.binding.BindingActivity 22 | import org.shortweather.util.extension.showToast 23 | 24 | @AndroidEntryPoint 25 | class SplashActivity : BindingActivity(R.layout.activity_splash) { 26 | private val viewModel by viewModels() 27 | 28 | override fun onCreate(savedInstanceState: Bundle?) { 29 | super.onCreate(savedInstanceState) 30 | viewModel.setDeviceToken(ShortWeatherSharedPreference.getDeviceToken(this)) // 디바이스 토큰 설정 31 | setObservers() 32 | Handler(Looper.getMainLooper()).postDelayed({ 33 | viewModel.searchUser() // 디바이스 토큰을 서버에 전송하여 유저 조회 34 | }, SPLASH_TIME) 35 | } 36 | 37 | private fun setObservers() { 38 | viewModel.searchUserEvent.observe( // 유저 조회 성공 시 Main으로, 실패 시 정보입력으로 39 | this, EventObserver { code -> 40 | when (code) { 41 | SUCCESS_200 -> { 42 | if (viewModel.getIsExist()) { 43 | startActivity(Intent(this, MainActivity::class.java)) 44 | } else { 45 | startActivity(Intent(this, InputInfoActivity::class.java)) 46 | } 47 | finish() 48 | } 49 | HTTP_EXCEPTION_400 -> showToast(getString(R.string.wait_server_error)) 50 | HTTP_EXCEPTION_401 -> showToast(getString(R.string.wait_server_error)) 51 | HTTP_EXCEPTION_500 -> showToast(getString(R.string.wait_server_error)) 52 | FAILURE -> showToast(getString(R.string.http_server_error)) 53 | } 54 | }) 55 | viewModel.accessTokenEvent.observe( // 유저 조회 성공하면 액세스토큰 기기에 저장 56 | this, EventObserver { accessToken -> 57 | if (accessToken != null) { 58 | ShortWeatherSharedPreference.setAccessToken(this, accessToken) 59 | } 60 | }) 61 | } 62 | 63 | companion object { 64 | private const val SPLASH_TIME: Long = 2800 65 | } 66 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/todayweathercontainer/OnPageDownClickListener.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.todayweathercontainer 2 | 3 | interface OnPageDownClickListener { 4 | fun pageDown() 5 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/todayweathercontainer/adapter/TodayWeatherContainerAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.todayweathercontainer.adapter 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentActivity 5 | import androidx.viewpager2.adapter.FragmentStateAdapter 6 | 7 | class TodayWeatherContainerAdapter( 8 | private val fragments: List, 9 | fragmentActivity: FragmentActivity 10 | ) : FragmentStateAdapter(fragmentActivity) { 11 | override fun getItemCount(): Int = fragments.size 12 | 13 | override fun createFragment(position: Int): Fragment = fragments[position] 14 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/todayweathercontainer/view/TodayWeatherContainerFragment.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.todayweathercontainer.view 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import androidx.fragment.app.viewModels 6 | import dagger.hilt.android.AndroidEntryPoint 7 | import org.shortweather.R 8 | import org.shortweather.databinding.FragmentTodayWeatherContainerBinding 9 | import org.shortweather.presentation.customweather.view.CustomWeatherFragment 10 | import org.shortweather.presentation.todayweather.view.TodayWeatherFragment 11 | import org.shortweather.presentation.todayweathercontainer.OnPageDownClickListener 12 | import org.shortweather.presentation.todayweathercontainer.adapter.TodayWeatherContainerAdapter 13 | import org.shortweather.presentation.todayweathercontainer.viewmodel.TodayWeatherContainerViewModel 14 | import org.shortweather.util.binding.BindingFragment 15 | 16 | @AndroidEntryPoint 17 | class TodayWeatherContainerFragment : 18 | BindingFragment(R.layout.fragment_today_weather_container) { 19 | private val viewModel: TodayWeatherContainerViewModel by viewModels() 20 | private val todayWeatherFragment = TodayWeatherFragment() 21 | private val customWeatherFragment = CustomWeatherFragment() 22 | 23 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 24 | super.onViewCreated(view, savedInstanceState) 25 | 26 | setAdapter() 27 | setOnPageDownClickListener() 28 | } 29 | 30 | private fun setAdapter() { 31 | binding.vpTodayWeatherContainer.adapter = TodayWeatherContainerAdapter( 32 | listOf(todayWeatherFragment, customWeatherFragment), 33 | requireActivity() 34 | ) 35 | } 36 | 37 | private fun setOnPageDownClickListener() { 38 | todayWeatherFragment.setOnPageDownClickListener(object : OnPageDownClickListener { 39 | override fun pageDown() { 40 | binding.vpTodayWeatherContainer.currentItem = 1 41 | } 42 | }) 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/todayweathercontainer/viewmodel/TodayWeatherContainerViewModel.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.todayweathercontainer.viewmodel 2 | 3 | import androidx.lifecycle.ViewModel 4 | import dagger.hilt.android.lifecycle.HiltViewModel 5 | import javax.inject.Inject 6 | 7 | @HiltViewModel 8 | class TodayWeatherContainerViewModel @Inject constructor() : ViewModel() { 9 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/waketimesetting/view/WakeTimeSettingActivity.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.waketimesetting.view 2 | 3 | import android.os.Bundle 4 | import androidx.activity.viewModels 5 | import dagger.hilt.android.AndroidEntryPoint 6 | import org.shortweather.R 7 | import org.shortweather.databinding.ActivityWakeTimeSettingBinding 8 | import org.shortweather.presentation.input.view.BottomSheetTimeFragment 9 | import org.shortweather.presentation.input.viewmodel.InputTimeViewModel 10 | import org.shortweather.util.EventObserver 11 | import org.shortweather.util.binding.BindingActivity 12 | import org.shortweather.util.extension.setOnThrottleClickListener 13 | 14 | @AndroidEntryPoint 15 | class WakeTimeSettingActivity : 16 | BindingActivity(R.layout.activity_wake_time_setting) { 17 | private val viewModel by viewModels() 18 | private var beforeTime = " " 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | binding.vm = viewModel // 데이터바인딩 23 | binding.lifecycleOwner = this 24 | binding.btnSettingWakeTimeCheck.isEnabled = false // 최초에는 확인 버튼의 Enable 상태 false 25 | setOnClickListener() 26 | setObservers() 27 | } 28 | 29 | private fun setObservers() { 30 | viewModel.isWakeDestroy.observe(this, EventObserver { isSuccess -> 31 | if (isSuccess && checkTimeChanged()) { 32 | binding.vSettingWakeTimeLine.setBackgroundResource(R.color.short_weather_blue) 33 | binding.btnSettingWakeTimeCheck.isEnabled = true 34 | } else { // 기상시간 변경 없이 단순히 선택되었다가 취소된 상황 35 | binding.vSettingWakeTimeLine.setBackgroundResource(R.color.short_weather_gray_1) 36 | binding.btnSettingWakeTimeCheck.isEnabled = false 37 | } 38 | }) 39 | } 40 | 41 | private fun setOnClickListener() { 42 | // 확인 버튼을 누르면 MainActivity로 이동 43 | binding.btnSettingWakeTimeCheck.setOnThrottleClickListener { 44 | // 메인 액티비티의 설정 프래그먼트로 이동 45 | // 서버에 시간 전달 46 | finish() 47 | } 48 | binding.layoutSettingWakeTime.setOnThrottleClickListener { // 기상시간 선택 바텀시트 호출 49 | beforeTime = viewModel.timeWake.value!! // 호출 전 기상시간 저장 50 | binding.vSettingWakeTimeLine.setBackgroundResource(R.color.short_weather_blue) 51 | BottomSheetTimeFragment.newInstance("wake") 52 | .show(supportFragmentManager, BottomSheetTimeFragment.TAG) 53 | } 54 | } 55 | 56 | private fun checkTimeChanged(): Boolean { // 호출 전후 설정된 기상시간이 달라지면 true 57 | if (viewModel.timeWake.value == beforeTime) { 58 | return false 59 | } 60 | return true 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/weeklyweather/adapter/WeeklyWeatherAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.weeklyweather.adapter 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.ListAdapter 6 | import androidx.recyclerview.widget.RecyclerView 7 | import org.shortweather.data.model.WeeklyWeather 8 | import org.shortweather.databinding.ItemWeeklyWeatherBinding 9 | import org.shortweather.util.ItemDiffCallback 10 | 11 | class WeeklyWeatherAdapter : 12 | ListAdapter( 13 | ItemDiffCallback( 14 | onItemsTheSame = { oldItem, newItem -> oldItem == newItem }, 15 | onContentsTheSame = { oldItem, newItem -> oldItem == newItem }) 16 | ) { 17 | private lateinit var inflater: LayoutInflater 18 | 19 | override fun onCreateViewHolder( 20 | parent: ViewGroup, 21 | viewType: Int 22 | ): WeeklyWeatherViewHolder { 23 | if (!::inflater.isInitialized) { 24 | inflater = LayoutInflater.from(parent.context) 25 | } 26 | return WeeklyWeatherViewHolder( 27 | ItemWeeklyWeatherBinding.inflate( 28 | inflater, 29 | parent, 30 | false 31 | ) 32 | ) 33 | } 34 | 35 | override fun onBindViewHolder(holder: WeeklyWeatherViewHolder, position: Int) { 36 | holder.onBind(currentList[position]) 37 | } 38 | 39 | class WeeklyWeatherViewHolder( 40 | private val binding: ItemWeeklyWeatherBinding 41 | ) : RecyclerView.ViewHolder(binding.root) { 42 | fun onBind(weather: WeeklyWeather) { 43 | binding.weeklyWeather = weather 44 | binding.executePendingBindings() 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/presentation/weeklyweather/view/WeeklyWeatherFragment.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.presentation.weeklyweather.view 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import androidx.fragment.app.viewModels 6 | import org.shortweather.R 7 | import org.shortweather.databinding.FragmentWeeklyWeatherBinding 8 | import org.shortweather.presentation.weeklyweather.adapter.WeeklyWeatherAdapter 9 | import org.shortweather.presentation.weeklyweather.viewmodel.WeeklyWeatherViewModel 10 | import org.shortweather.util.binding.BindingFragment 11 | 12 | class WeeklyWeatherFragment : 13 | BindingFragment(R.layout.fragment_weekly_weather) { 14 | private val viewModel by viewModels() 15 | private val adapter = WeeklyWeatherAdapter() 16 | 17 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 18 | super.onViewCreated(view, savedInstanceState) 19 | 20 | initView() 21 | setAdapter() 22 | setOnRefreshListener() 23 | } 24 | 25 | private fun initView() { 26 | adapter.submitList(viewModel.getMockWeeklyWeatherList()) 27 | } 28 | 29 | private fun setOnRefreshListener() { 30 | binding.srlWeeklyWeather.setOnRefreshListener { 31 | adapter.submitList(viewModel.getMockWeeklyWeatherList()) 32 | binding.srlWeeklyWeather.isRefreshing = false 33 | } 34 | } 35 | 36 | private fun setAdapter() { 37 | binding.rvWeeklyWeather.adapter = adapter 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/Constants.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util 2 | 3 | object Constants { 4 | const val WEATHER = "weather" 5 | const val FINE_DUST = "fineDust" 6 | const val GENDER = "gender" 7 | const val AGE = "age" 8 | const val SENSE = "sense" 9 | const val WAKE = "wake" 10 | const val OUT = "out" 11 | const val RETURN = "return" 12 | const val SUCCESS_200 = 200 13 | const val SUCCESS_201 = 201 14 | const val HTTP_EXCEPTION_400 = 400 15 | const val HTTP_EXCEPTION_401 = 401 16 | const val HTTP_EXCEPTION_500 = 500 17 | const val FAILURE = 0 18 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/Event.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util 2 | 3 | class Event(private val content: T) { 4 | private var hasBeenHandled = false 5 | 6 | fun getContentIfNotHandled(): T? { 7 | return if (hasBeenHandled) { 8 | null 9 | } else { 10 | hasBeenHandled = true 11 | content 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/EventObserver.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util 2 | 3 | import androidx.lifecycle.Observer 4 | 5 | class EventObserver(private val onEventUnhandledContent: (T) -> Unit) : Observer> { 6 | override fun onChanged(event: Event?) { 7 | event?.getContentIfNotHandled()?.let { 8 | onEventUnhandledContent(it) 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/ItemDiffCallback.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util 2 | 3 | import androidx.recyclerview.widget.DiffUtil 4 | 5 | class ItemDiffCallback( 6 | val onItemsTheSame: (T, T) -> Boolean, 7 | val onContentsTheSame: (T, T) -> Boolean, 8 | ) : DiffUtil.ItemCallback() { 9 | override fun areItemsTheSame(oldItem: T, newItem: T): Boolean = onItemsTheSame(oldItem, newItem) 10 | override fun areContentsTheSame(oldItem: T, newItem: T): Boolean = 11 | onContentsTheSame(oldItem, newItem) 12 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/OnThrottleClickListener.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util 2 | 3 | import android.util.Log 4 | import android.view.View 5 | 6 | class OnThrottleClickListener( // 뷰의 중복 클릭을 막기 위한 리스너 7 | private val clickListener: View.OnClickListener, 8 | private val interval: Long = 500 9 | ) : 10 | View.OnClickListener { 11 | 12 | private var clickable = true 13 | // clickable 플래그를 이 클래스가 아니라 더 상위 클래스에 두면 14 | // 여러 뷰에 대한 중복 클릭 방지할 수 있다. 15 | 16 | override fun onClick(v: View?) { 17 | if (clickable) { 18 | clickable = false 19 | v?.run { 20 | postDelayed({ 21 | clickable = true 22 | }, interval) 23 | clickListener.onClick(v) 24 | } 25 | } else { 26 | Log.d("tag", "waiting for a while") 27 | } 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/ShortWeatherFirebaseMessagingService.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util 2 | 3 | import com.google.firebase.messaging.FirebaseMessagingService 4 | 5 | class ShortWeatherFirebaseMessagingService : FirebaseMessagingService() { 6 | override fun onNewToken(token: String) { 7 | super.onNewToken(token) 8 | } 9 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/ShortWeatherSharedPreference.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import com.google.firebase.messaging.FirebaseMessaging 6 | 7 | object ShortWeatherSharedPreference { 8 | fun setAccessToken(context: Context, token: String) { // 액세스 토큰 설정 9 | val sharedPreferences: SharedPreferences = 10 | context.getSharedPreferences("tokens", Context.MODE_PRIVATE) 11 | val editor: SharedPreferences.Editor = sharedPreferences.edit() 12 | editor.putString("AccessToken", token) 13 | editor.apply() 14 | } 15 | 16 | fun getAccessToken(context: Context): String { // 저장된 액세스 토큰 반환 17 | val prefs: SharedPreferences = 18 | context.getSharedPreferences("tokens", Context.MODE_PRIVATE) 19 | return prefs.getString("AccessToken", "").toString() 20 | } 21 | 22 | fun setDeviceToken(context: Context) { // 디바이스 토큰 설정 23 | FirebaseMessaging.getInstance().token.addOnSuccessListener { 24 | if (!it.isNullOrEmpty()) { 25 | val sharedPreferences: SharedPreferences = 26 | context.getSharedPreferences("tokens", Context.MODE_PRIVATE) 27 | val editor: SharedPreferences.Editor = sharedPreferences.edit() 28 | editor.putString("DeviceToken", it) 29 | editor.apply() 30 | } 31 | } 32 | } 33 | 34 | fun getDeviceToken(context: Context): String { // 저장된 디바이스 토큰 반환 35 | val prefs: SharedPreferences = 36 | context.getSharedPreferences("tokens", Context.MODE_PRIVATE) 37 | return prefs.getString("DeviceToken", "").toString() 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/binding/BindingActivity.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util.binding 2 | 3 | import android.os.Bundle 4 | import androidx.annotation.LayoutRes 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.databinding.DataBindingUtil 7 | import androidx.databinding.ViewDataBinding 8 | 9 | abstract class BindingActivity(@LayoutRes private val layoutRes: Int) : 10 | AppCompatActivity() { 11 | protected lateinit var binding: T 12 | 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | binding = DataBindingUtil.setContentView(this, layoutRes) 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/binding/BindingFragment.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util.binding 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.annotation.LayoutRes 8 | import androidx.databinding.DataBindingUtil 9 | import androidx.databinding.ViewDataBinding 10 | import androidx.fragment.app.Fragment 11 | 12 | abstract class BindingFragment(@LayoutRes private val layoutRes: Int) : 13 | Fragment() { 14 | private var _binding: T? = null 15 | protected val binding: T 16 | get() = requireNotNull(_binding) { "${this::class.java.simpleName} error." } 17 | 18 | override fun onCreateView( 19 | inflater: LayoutInflater, 20 | container: ViewGroup?, 21 | savedInstanceState: Bundle? 22 | ): View { 23 | _binding = DataBindingUtil.inflate(inflater, layoutRes, container, false) 24 | return binding.root 25 | } 26 | 27 | override fun onDestroyView() { 28 | super.onDestroyView() 29 | _binding = null 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/extension/ActivityExt.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util.extension 2 | 3 | import android.view.View 4 | import androidx.annotation.IdRes 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.fragment.app.Fragment 7 | import androidx.fragment.app.commit 8 | import androidx.fragment.app.replace 9 | 10 | inline fun AppCompatActivity.replace(@IdRes frameId: Int) { 11 | supportFragmentManager.commit { 12 | replace(frameId) 13 | setReorderingAllowed(true) 14 | } 15 | } 16 | 17 | fun AppCompatActivity.hideKeyboard() { 18 | hideKeyboard(currentFocus ?: View(this)) 19 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/extension/ContextExt.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util.extension 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.view.View 6 | import android.view.inputmethod.InputMethodManager 7 | import android.widget.Toast 8 | 9 | fun Context.hideKeyboard(view: View) { 10 | val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager 11 | inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0) 12 | } 13 | 14 | fun Context.showToast(message: String, isShort: Boolean = true) { 15 | Toast.makeText(this, message, if (isShort) Toast.LENGTH_SHORT else Toast.LENGTH_LONG).show() 16 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/extension/LiveDataExt.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util.extension 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MediatorLiveData 5 | 6 | fun MediatorLiveData.addSourceList( 7 | vararg liveDataArgument: LiveData<*>, 8 | onChanged: () -> T 9 | ) { 10 | liveDataArgument.forEach { 11 | this.addSource(it) { value = onChanged() } 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/org/shortweather/util/extension/ViewExt.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather.util.extension 2 | 3 | import android.view.View 4 | import org.shortweather.util.OnThrottleClickListener 5 | 6 | fun View.setOnThrottleClickListener(action: (v: View) -> Unit) { 7 | val listener = View.OnClickListener { action(it) } 8 | setOnClickListener(OnThrottleClickListener(listener)) 9 | } 10 | 11 | // with interval setting 12 | fun View.setOnThrottleClickListener(action: (v: View) -> Unit, interval: Long) { 13 | val listener = View.OnClickListener { action(it) } 14 | setOnClickListener(OnThrottleClickListener(listener, interval)) 15 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_clear_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_clear_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_clear_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_clear_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_cloudy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_lightrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_lightrain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_lightsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_lightsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_lotcloud_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_lotcloud_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_lotcloud_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_lotcloud_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_rain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_rainsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_rainsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_shower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_shower.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_snow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/img_snowdrifting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-hdpi/img_snowdrifting.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_clear_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_clear_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_clear_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_clear_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_cloudy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_lightrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_lightrain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_lightsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_lightsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_lotcloud_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_lotcloud_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_lotcloud_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_lotcloud_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_rain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_rainsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_rainsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_shower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_shower.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_snow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_snowdrifting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xhdpi/img_snowdrifting.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_clear_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_clear_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_clear_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_clear_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_cloudy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_lightrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_lightrain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_lightsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_lightsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_lotcloud_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_lotcloud_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_lotcloud_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_lotcloud_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_rain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_rainsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_rainsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_shower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_shower.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_snow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_snowdrifting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxhdpi/img_snowdrifting.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_clear_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_clear_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_clear_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_clear_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_cloudy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_lightrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_lightrain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_lightsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_lightsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_lotcloud_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_lotcloud_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_lotcloud_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_lotcloud_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_rain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_rainsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_rainsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_shower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_shower.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_snow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/img_snowdrifting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable-xxxhdpi/img_snowdrifting.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_bad_dust.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_blue_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_blue_newsflash.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_bottom_sheet.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_bottom_sheet_btn_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_bottom_sheet_btn_gray.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_cloud.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_day.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_fog.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_good_dust.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_gray_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_night.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_nomal_dust.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_rain.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_red_newsflash.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_snow.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_today_weather_description.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_today_weather_sub_description.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_today_weather_toast.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_windy.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_worst_dust.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_yellow_newsflash.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_yellowdust.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_input_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_sheet_drag_view.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_clear_day.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_clear_night.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_clothes.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cloudy.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dust_bad.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 12 | 15 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dust_good.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 12 | 16 | 20 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dust_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 12 | 15 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dust_worst.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 12 | 16 | 19 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_down.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_red.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_right.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fog.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_hail.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 18 | 21 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_hamberger.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_heavyrain.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | 17 | 21 | 25 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_humidity.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lightning.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lightrain.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | 17 | 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_littlecloud_day.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_littlecloud_night.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_location.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lotcloud_day.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lotcloud_night.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_next_btn.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_1.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_10.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_2.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_3.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_4.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_5.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_6.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_7.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_8.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_precipitation_9.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_rain.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | 17 | 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_setting.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shower.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | 17 | 21 | 25 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_snow.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_snowdrifting.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sunrise.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sunset.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_toast.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_today.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_week.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_weekly_weather_example.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_windy.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_yellowdust.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_clear_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_clear_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_clear_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_clear_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_cloudy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_lightrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_lightrain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_lightsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_lightsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_lotcloud_day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_lotcloud_day.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_lotcloud_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_lotcloud_night.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_rain.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_rainsnow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_rainsnow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_shower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_shower.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_snow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_snowdrifting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/drawable/img_snowdrifting.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_input_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_input_btn_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_black.otf -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_bold.otf -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_extrabold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_extrabold.otf -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_extralight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_extralight.otf -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_light.otf -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_medium.otf -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_regular.otf -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_semibold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_semibold.otf -------------------------------------------------------------------------------- /app/src/main/res/font/pretendard_thin.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/font/pretendard_thin.otf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/bottom_sheet_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 22 | 23 | 31 | 32 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/bottom_sheet_time_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 21 | 22 | 28 | 29 | 38 | 39 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_today_weather_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_bottom_sheet.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_custom_weather_precipitation.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 16 | 17 | 28 | 29 | 39 | 40 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_custom_weather_weather.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 16 | 17 | 28 | 29 | 40 | 41 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_drawer_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_today_weather_fine_dust.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 15 | 16 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_today_weather_newsflash.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 15 | 16 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_today_weather_ultrafine_dust.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 15 | 16 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | 16 | 17 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_tool_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_short_weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-hdpi/ic_short_weather.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_short_weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-mdpi/ic_short_weather.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_short_weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xhdpi/ic_short_weather.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_short_weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xxhdpi/ic_short_weather.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_short_weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/app/src/main/res/mipmap-xxxhdpi/ic_short_weather.png -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #FFBB86FC 5 | #FF6200EE 6 | #FF3700B3 7 | #FF03DAC5 8 | #FF018786 9 | #FF000000 10 | #FFFFFFFF 11 | 12 | 13 | #000000 14 | #2F2F2F 15 | #717171 16 | #7D7F84 17 | #919499 18 | #A7A7A7 19 | #DCDCDC 20 | #EBEBEB 21 | #F2F2F2 22 | #F8F8F8 23 | #FFFFFF 24 | #5C7EFF 25 | #FFF6DD 26 | #FF8383 27 | #E0F0FB 28 | #9AC4F3 29 | #7390FF 30 | #CDF1D5 31 | #59B06D 32 | #FFEFB6 33 | #E0AE56 34 | #FFC700 35 | #FF974B 36 | #FFDADC 37 | #EDC9C9 38 | #E4626A 39 | #8B3939 40 | #B774DA 41 | #FF4F4F 42 | #73FFFFFF 43 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/test/java/org/shortweather/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package org.shortweather 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext { 4 | activity_ktx_version = '1.6.0' 5 | fragment_ktx_version = '1.5.3' 6 | lifecycle_version = '2.5.1' 7 | retrofit_version = '2.9.0' 8 | okhttp_version = '4.10.0' 9 | kotlinx_serialization_version = '1.4.1' 10 | kotlinx_serialization_converter_version = '0.8.0' 11 | hilt_version = '2.44' 12 | dotsindicator_version = '4.3' 13 | lottie_version = '5.2.0' 14 | swipe_refresh_layout_version = '1.1.0' 15 | switch_button_version = '0.0.3@aar' 16 | fcm_version = '23.1.1' 17 | fb_messaging_version = '23.1.1' 18 | fb_bom_version = '31.1.1' 19 | } 20 | repositories { 21 | mavenCentral() 22 | google() 23 | } 24 | 25 | dependencies { 26 | classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" 27 | classpath 'com.google.gms:google-services:4.3.14' 28 | } 29 | } 30 | 31 | plugins { 32 | id 'com.android.application' version '7.3.0' apply false 33 | id 'com.android.library' version '7.3.0' apply false 34 | id 'org.jetbrains.kotlin.android' version '1.7.10' apply false 35 | id 'com.google.gms.google-services' version '4.3.10' apply false 36 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official 20 | # Enables namespacing of each library's R class so that its R class includes only the 21 | # resources declared in the library itself and none from the library's dependencies, 22 | # thereby reducing the size of the R class for that library 23 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamShortWeather/ShortWeather-AOS/5df67c7d835f3e3cac496e9410c14d9ba5a7b130/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Dec 29 21:42:18 KST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "ShortWeather" 16 | include ':app' 17 | --------------------------------------------------------------------------------