diff --git a/.gitignore b/.gitignore index fd18cac..e96e488 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,90 @@ -*.iml +### AndroidStudio ### +# Covers files to be ignored for android development using Android Studio. + +# Built application files +*.apk +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files .gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -/.idea/caches -.DS_Store -/build -/captures +.gradle/ +build/ + +# Signing files +.signing/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio +/*/build/ +/*/local.properties +/*/out +/*/*/build +/*/*/production +captures/ +.navigation/ +*.ipr +*~ +*.swp + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Android Patch +gen-external-apklibs + +# External native build folder generated in Android Studio 2.2 and later .externalNativeBuild -/projectFilesBackup + +# IntelliJ IDEA +*.iml +*.iws +/out/ + +# User-specific configurations +.idea/caches/ +.idea/libraries/ +.idea/shelf/ +.idea/workspace.xml +.idea/tasks.xml +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/misc.xml +.idea/modules.xml +.idea/scopes/scope_settings.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml +.idea/datasources.xml +.idea/dataSources.ids +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml +.idea/assetWizardSettings.xml +.idea/gradle.xml +.idea/jarRepositorie diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser deleted file mode 100644 index cc7c455..0000000 Binary files a/.idea/caches/build_file_checksums.ser and /dev/null differ diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 5cd135a..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 23cea1a..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index d401ed3..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 7ac2d90..1284a4c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -97,6 +97,7 @@ dependencies { implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2' implementation 'androidx.navigation:navigation-ui-ktx:2.3.2' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2' + implementation 'androidx.test.espresso:espresso-idling-resource:3.4.0' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2' androidTestImplementation 'com.android.support.test:rules:1.0.2' // Unit testing @@ -108,8 +109,8 @@ dependencies { // android unit testing and espresso androidTestImplementation 'androidx.test.ext:junit:1.1.1' - implementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + androidTestImplementation 'androidx.test:rules:1.4.1-alpha06' //mock websever for testing retrofit responses testImplementation "com.squareup.okhttp3:mockwebserver:4.6.0" testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" @@ -117,7 +118,6 @@ dependencies { //mockito and livedata testing testImplementation 'org.mockito:mockito-inline:2.13.0' implementation 'android.arch.core:core-testing' - androidTestImplementation 'androidx.test:rules:1.3.0-rc01' // Mockk def mockk_ver = "1.10.5" diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt index 9fdb4a8..2ac83f4 100644 --- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt +++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt @@ -1,16 +1,17 @@ package com.appttude.h_mal.atlas_weather.application +import androidx.room.Room import androidx.test.espresso.IdlingRegistry import androidx.test.espresso.idling.CountingIdlingResource -import com.appttude.h_mal.atlas_weather.R import com.appttude.h_mal.atlas_weather.data.location.MockLocationProvider -import com.appttude.h_mal.atlas_weather.data.network.Api import com.appttude.h_mal.atlas_weather.data.network.NetworkModule import com.appttude.h_mal.atlas_weather.data.network.WeatherApi import com.appttude.h_mal.atlas_weather.data.network.interceptors.MockingNetworkInterceptor import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor import com.appttude.h_mal.atlas_weather.data.network.networkUtils.loggingInterceptor +import com.appttude.h_mal.atlas_weather.data.room.AppDatabase +import com.appttude.h_mal.atlas_weather.data.room.Converter import java.io.BufferedReader class TestAppClass : BaseAppClass() { @@ -22,17 +23,23 @@ class TestAppClass : BaseAppClass() { IdlingRegistry.getInstance().register(idlingResources) } - override fun createNetworkModule(): Api { + override fun createNetworkModule(): WeatherApi { return NetworkModule().invoke( + mockingNetworkInterceptor, NetworkConnectionInterceptor(this), QueryParamsInterceptor(), - loggingInterceptor, - mockingNetworkInterceptor - ) + loggingInterceptor + ) as WeatherApi } override fun createLocationModule() = MockLocationProvider() + override fun createRoomDatabase(): AppDatabase { + return Room.inMemoryDatabaseBuilder(this, AppDatabase::class.java) + .addTypeConverter(Converter(this)) + .build() + } + fun stubUrl(url: String, rawPath: String) { val id = resources.getIdentifier(rawPath, "raw", packageName) val iStream = resources.openRawResource(id) @@ -40,7 +47,7 @@ class TestAppClass : BaseAppClass() { mockingNetworkInterceptor.addUrlStub(url = url, data = data) } - fun removeUrlStub(url: String){ + fun removeUrlStub(url: String) { mockingNetworkInterceptor.removeUrlStub(url = url) } diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/BaseTest.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/BaseTest.kt index 68138e5..21509cd 100644 --- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/BaseTest.kt +++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/BaseTest.kt @@ -1,5 +1,12 @@ package com.appttude.h_mal.atlas_weather.monoWeather.testsuite +import android.content.Intent +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.pressBack +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule import com.appttude.h_mal.atlas_weather.application.TestAppClass @@ -21,6 +28,12 @@ open class BaseTest { testApp = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass setupFeed() } + + override fun afterActivityLaunched() { + + // Dismiss dialog + onView(withText("AGREE")).inRoot(isDialog()).check(matches(isDisplayed())).perform(ViewActions.click()) + } } fun stubEndpoint(url: String, stub: Stubs) { @@ -32,8 +45,7 @@ open class BaseTest { } @After - fun tearDown() { - } + fun tearDown() {} open fun setupFeed() {} } \ No newline at end of file diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/HomePageUITest.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/HomePageUITest.kt index 5972ca7..5ec092a 100644 --- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/HomePageUITest.kt +++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/HomePageUITest.kt @@ -1,6 +1,11 @@ package com.appttude.h_mal.atlas_weather.monoWeather.testsuite +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.RootMatchers +import androidx.test.espresso.matcher.ViewMatchers import androidx.test.rule.GrantPermissionRule import com.appttude.h_mal.atlas_weather.monoWeather.robot.homeScreen import com.appttude.h_mal.atlas_weather.utils.Stubs diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/HomePageUITestScenario.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/HomePageUITestScenario.kt new file mode 100644 index 0000000..9840120 --- /dev/null +++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/monoWeather/testsuite/HomePageUITestScenario.kt @@ -0,0 +1,85 @@ +package com.appttude.h_mal.atlas_weather.monoWeather.testsuite + + +import androidx.lifecycle.Lifecycle +import androidx.test.core.app.ActivityScenario +import androidx.test.core.app.ActivityScenario.launch +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.RootMatchers +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.rule.GrantPermissionRule +import com.appttude.h_mal.atlas_weather.application.TestAppClass +import com.appttude.h_mal.atlas_weather.monoWeather.robot.homeScreen +import com.appttude.h_mal.atlas_weather.monoWeather.ui.MainActivity +import com.appttude.h_mal.atlas_weather.utils.Stubs +import kotlinx.coroutines.runBlocking +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4ClassRunner::class) +class HomePageUITestScenario : BaseMainScenario() { + + @Rule + @JvmField + var mGrantPermissionRule: GrantPermissionRule = + GrantPermissionRule.grant( + "android.permission.ACCESS_COARSE_LOCATION") + + override fun setupFeed() { + stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Valid) + } + + @Test + fun loadApp_validWeatherResponse_returnsValidPage() { + homeScreen { + verifyCurrentTemperature(2) + verifyCurrentLocation("Mock Location") + } + } +} + +open class BaseMainScenario { + + lateinit var scenario: ActivityScenario + private lateinit var testApp : TestAppClass + + @Before + fun setUp() { + scenario = launch(MainActivity::class.java) + scenario.moveToState(Lifecycle.State.INITIALIZED) + scenario.onActivity { + runBlocking { + testApp = it.application as TestAppClass + setupFeed() + } + } + + scenario.moveToState(Lifecycle.State.CREATED).onActivity { + Espresso.onView(ViewMatchers.withText("AGREE")) + .inRoot(RootMatchers.isDialog()) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + .perform(ViewActions.click()) + } + } + + fun stubEndpoint(url: String, stub: Stubs) { + testApp.stubUrl(url, stub.id) + } + + fun unstubEndpoint(url: String) { + testApp.removeUrlStub(url) + } + + @After + fun tearDown() {} + + open fun setupFeed() {} +} diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/application/AppClass.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/application/AppClass.kt index 3af5874..4a537c6 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/application/AppClass.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/application/AppClass.kt @@ -1,5 +1,6 @@ package com.appttude.h_mal.atlas_weather.application +import androidx.room.RoomDatabase import com.appttude.h_mal.atlas_weather.data.location.LocationProvider import com.appttude.h_mal.atlas_weather.data.location.LocationProviderImpl import com.appttude.h_mal.atlas_weather.data.network.Api @@ -26,14 +27,16 @@ const val LOCATION_PERMISSION_REQUEST = 505 class AppClass : BaseAppClass() { - override fun createNetworkModule(): Api { + override fun createNetworkModule(): WeatherApi { return NetworkModule().invoke( NetworkConnectionInterceptor(this), QueryParamsInterceptor(), loggingInterceptor - ) + ) as WeatherApi } override fun createLocationModule() = LocationProviderImpl(this) + override fun createRoomDatabase(): AppDatabase = AppDatabase(this) + } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/application/BaseAppClass.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/application/BaseAppClass.kt index e19dc00..ebd54a1 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/application/BaseAppClass.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/application/BaseAppClass.kt @@ -1,15 +1,8 @@ package com.appttude.h_mal.atlas_weather.application import android.app.Application -import androidx.test.espresso.idling.CountingIdlingResource import com.appttude.h_mal.atlas_weather.data.location.LocationProvider -import com.appttude.h_mal.atlas_weather.data.location.LocationProviderImpl -import com.appttude.h_mal.atlas_weather.data.network.Api -import com.appttude.h_mal.atlas_weather.data.network.NetworkModule import com.appttude.h_mal.atlas_weather.data.network.WeatherApi -import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor -import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor -import com.appttude.h_mal.atlas_weather.data.network.networkUtils.loggingInterceptor import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider import com.appttude.h_mal.atlas_weather.data.repository.RepositoryImpl import com.appttude.h_mal.atlas_weather.data.repository.SettingsRepositoryImpl @@ -31,11 +24,11 @@ abstract class BaseAppClass : Application(), KodeinAware { override val kodein = Kodein.lazy { import(androidXModule(this@BaseAppClass)) - bind() from singleton { createNetworkModule() as WeatherApi} + bind() from singleton { createNetworkModule() } bind() from singleton { createLocationModule() } bind() from singleton { Gson() } - bind() from singleton { AppDatabase(instance()) } + bind() from singleton { createRoomDatabase() } bind() from singleton { PreferenceProvider(instance()) } bind() from singleton { RepositoryImpl(instance(), instance(), instance()) } bind() from singleton { SettingsRepositoryImpl(instance()) } @@ -43,7 +36,8 @@ abstract class BaseAppClass : Application(), KodeinAware { bind() from provider { ApplicationViewModelFactory(instance(), instance()) } } - abstract fun createNetworkModule() : Api - abstract fun createLocationModule() : LocationProvider + abstract fun createNetworkModule(): WeatherApi + abstract fun createLocationModule(): LocationProvider + abstract fun createRoomDatabase(): AppDatabase } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/data/room/Converter.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/data/room/Converter.kt index 684062e..8e0a7f4 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/data/room/Converter.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/data/room/Converter.kt @@ -10,19 +10,18 @@ import org.kodein.di.android.kodein import org.kodein.di.generic.instance @ProvidedTypeConverter -class Converter(context: Context): KodeinAware{ +class Converter(context: Context) : KodeinAware { override val kodein by kodein(context) private val gson by instance() @TypeConverter - fun fullWeatherToString(fullWeather: FullWeather): String{ + fun fullWeatherToString(fullWeather: FullWeather): String { return gson.toJson(fullWeather) } @TypeConverter - fun stringToFullWeather(string: String): FullWeather{ + fun stringToFullWeather(string: String): FullWeather { return gson.fromJson(string, FullWeather::class.java) } - } diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/dialog/PermissionsDeclarationDialog.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/dialog/PermissionsDeclarationDialog.kt index 5476e7b..9302dec 100644 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/dialog/PermissionsDeclarationDialog.kt +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/dialog/PermissionsDeclarationDialog.kt @@ -20,7 +20,7 @@ abstract class BaseDeclarationDialog(val context: Context): DeclarationBuilder { abstract override val link: String abstract override val message: String - fun showDialog(agreeCallback: () -> Unit = { Unit }, disagreeCallback: () -> Unit = { Unit }) { + fun showDialog(agreeCallback: () -> Unit = { }, disagreeCallback: () -> Unit = { Unit }) { val myMessage = buildMessage() val builder = AlertDialog.Builder(context) diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/BaseFragment.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/BaseFragment.kt index 641dfac..0efeeaf 100644 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/BaseFragment.kt +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/BaseFragment.kt @@ -2,15 +2,18 @@ package com.appttude.h_mal.atlas_weather.monoWeather.ui import android.animation.Animator import android.animation.AnimatorListenerAdapter +import android.annotation.SuppressLint import android.content.pm.PackageManager import android.os.Bundle import android.view.View +import androidx.annotation.LayoutRes import androidx.core.app.ActivityCompat import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.Observer import androidx.lifecycle.ViewModel import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import com.appttude.h_mal.atlas_weather.application.LOCATION_PERMISSION_REQUEST import com.appttude.h_mal.atlas_weather.utils.Event import com.appttude.h_mal.atlas_weather.utils.displayToast import com.appttude.h_mal.atlas_weather.utils.hide @@ -24,7 +27,7 @@ import org.kodein.di.android.x.kodein import org.kodein.di.generic.instance import kotlin.properties.Delegates -abstract class BaseFragment : Fragment(), KodeinAware { +abstract class BaseFragment(@LayoutRes contentLayoutId: Int) : Fragment(contentLayoutId), KodeinAware { override val kodein by kodein() val factory by instance() @@ -119,4 +122,21 @@ abstract class BaseFragment : Fragment(), KodeinAware { } } + @SuppressLint("MissingPermission") + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (requestCode == LOCATION_PERMISSION_REQUEST) { + if (grantResults.isNotEmpty() && + grantResults[0] == PackageManager.PERMISSION_GRANTED) { + permissionsGranted() + displayToast("Permission granted") + } else { + permissionsRefused() + displayToast("Permission denied") + } + } + } + + open fun permissionsGranted() {} + open fun permissionsRefused() {} } \ No newline at end of file diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/WorldItemFragment.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/WorldItemFragment.kt index 8be467c..495a734 100644 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/WorldItemFragment.kt +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/WorldItemFragment.kt @@ -14,7 +14,7 @@ import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel import kotlinx.android.synthetic.main.fragment_home.* -class WorldItemFragment : BaseFragment() { +class WorldItemFragment : BaseFragment(R.layout.fragment_home) { private val viewModel by getFragmentViewModel() private var param1: String? = null @@ -24,12 +24,6 @@ class WorldItemFragment : BaseFragment() { param1 = WorldItemFragmentArgs.fromBundle(requireArguments()).locationName } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_home, container, false) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/home/HomeFragment.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/home/HomeFragment.kt index 81e97f6..a3f09af 100644 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/home/HomeFragment.kt +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/home/HomeFragment.kt @@ -1,6 +1,7 @@ package com.appttude.h_mal.atlas_weather.monoWeather.ui.home import android.Manifest +import android.Manifest.permission.ACCESS_COARSE_LOCATION import android.annotation.SuppressLint import android.content.pm.PackageManager import android.os.Bundle @@ -11,6 +12,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.observe import com.appttude.h_mal.atlas_weather.R import com.appttude.h_mal.atlas_weather.application.LOCATION_PERMISSION_REQUEST +import com.appttude.h_mal.atlas_weather.model.forecast.Forecast import com.appttude.h_mal.atlas_weather.monoWeather.dialog.PermissionsDeclarationDialog import com.appttude.h_mal.atlas_weather.monoWeather.ui.BaseFragment import com.appttude.h_mal.atlas_weather.monoWeather.ui.home.adapter.WeatherRecyclerAdapter @@ -24,36 +26,29 @@ import kotlinx.android.synthetic.main.fragment_home.* * A simple [Fragment] subclass. * create an instance of this fragment. */ -class HomeFragment : BaseFragment() { +class HomeFragment : BaseFragment(R.layout.fragment_home) { private val viewModel by getFragmentViewModel() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_home, container, false) - } - @SuppressLint("MissingPermission") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val recyclerAdapter = WeatherRecyclerAdapter { - val directions = - HomeFragmentDirections.actionHomeFragmentToFurtherDetailsFragment(it) - navigateTo(directions) - } + val recyclerAdapter = WeatherRecyclerAdapter(itemClick = { + navigateToFurtherDetails(it) + }) forecast_listview.adapter = recyclerAdapter PermissionsDeclarationDialog(requireContext()).showDialog(agreeCallback = { - getPermissionResult(Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST) { + getPermissionResult(ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST) { viewModel.fetchData() } }) swipe_refresh.apply { setOnRefreshListener { - getPermissionResult(Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST) { + getPermissionResult(ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST) { viewModel.fetchData() isRefreshing = true } @@ -70,16 +65,13 @@ class HomeFragment : BaseFragment() { } @SuppressLint("MissingPermission") - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (requestCode == LOCATION_PERMISSION_REQUEST) { - if (grantResults.isNotEmpty() - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - viewModel.fetchData() - displayToast("Permission granted") - } else { - displayToast("Permission denied") - } - } + override fun permissionsGranted() { + viewModel.fetchData() + } + + private fun navigateToFurtherDetails(forecast: Forecast){ + val directions = HomeFragmentDirections + .actionHomeFragmentToFurtherDetailsFragment(forecast) + navigateTo(directions) } } \ No newline at end of file diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/AddLocationFragment.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/AddLocationFragment.kt index 203372c..16c280d 100644 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/AddLocationFragment.kt +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/AddLocationFragment.kt @@ -14,16 +14,10 @@ import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel import kotlinx.android.synthetic.main.activity_add_forecast.* -class AddLocationFragment : BaseFragment() { +class AddLocationFragment : BaseFragment(R.layout.activity_add_forecast) { private val viewModel by getFragmentViewModel() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.activity_add_forecast, container, false) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/WorldFragment.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/WorldFragment.kt index f1a9198..f8f66cd 100644 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/WorldFragment.kt +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/WorldFragment.kt @@ -22,7 +22,7 @@ import kotlinx.android.synthetic.main.fragment_add_location.world_recycler * A simple [Fragment] subclass. * create an instance of this fragment. */ -class WorldFragment : BaseFragment() { +class WorldFragment : BaseFragment(R.layout.fragment__two) { private val viewModel by getFragmentViewModel() override fun onCreate(savedInstanceState: Bundle?) { @@ -31,12 +31,6 @@ class WorldFragment : BaseFragment() { viewModel.fetchAllLocations() } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment__two, container, false) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/WorldRecyclerAdapter.kt b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/WorldRecyclerAdapter.kt index b7af3ed..0e14a88 100644 --- a/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/WorldRecyclerAdapter.kt +++ b/app/src/monoWeather/java/com/appttude/h_mal/atlas_weather/monoWeather/ui/world/WorldRecyclerAdapter.kt @@ -12,8 +12,8 @@ import com.appttude.h_mal.atlas_weather.utils.generateView import com.appttude.h_mal.atlas_weather.utils.loadImage class WorldRecyclerAdapter( - val itemClick: (WeatherDisplay) -> Unit, - val itemLongClick: (String) -> Unit + private val itemClick: (WeatherDisplay) -> Unit, + private val itemLongClick: (String) -> Unit ) : RecyclerView.Adapter() { var weather: MutableList = mutableListOf() @@ -78,23 +78,28 @@ class WorldRecyclerAdapter( return if (weather.size == 0) 1 else weather.size } - internal class WorldHolderCurrent(listItemView: View) : RecyclerView.ViewHolder(listItemView) { + internal class WorldHolderCurrent(cellView: View) : BaseViewHolder(cellView) { - var locationTV: TextView = listItemView.findViewById(R.id.db_location) - var conditionTV: TextView = listItemView.findViewById(R.id.db_condition) - var weatherIV: ImageView = listItemView.findViewById(R.id.db_icon) - var avgTempTV: TextView = listItemView.findViewById(R.id.db_main_temp) - var tempUnit: TextView = listItemView.findViewById(R.id.db_temp_unit) + private val locationTV: TextView = cellView.findViewById(R.id.db_location) + private val conditionTV: TextView = cellView.findViewById(R.id.db_condition) + private val weatherIV: ImageView = cellView.findViewById(R.id.db_icon) + private val avgTempTV: TextView = cellView.findViewById(R.id.db_main_temp) + private val tempUnit: TextView = cellView.findViewById(R.id.db_temp_unit) - fun bindData(weather: WeatherDisplay?){ - locationTV.text = weather?.displayName - conditionTV.text = weather?.description - weatherIV.loadImage(weather?.iconURL) - avgTempTV.text = weather?.forecast?.get(0)?.mainTemp + override fun bindData(data: WeatherDisplay?){ + locationTV.text = data?.displayName + conditionTV.text = data?.description + weatherIV.loadImage(data?.iconURL) + avgTempTV.text = data?.forecast?.get(0)?.mainTemp tempUnit.text = itemView.context.getString(R.string.degrees) } } + abstract class BaseViewHolder(cellView: View) : RecyclerView.ViewHolder(cellView) { + + abstract fun bindData(data : T?) + } + } \ No newline at end of file