diff --git a/.circleci/config.yml b/.circleci/config.yml index e1a2c21..0c072fb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,9 +15,15 @@ commands: steps: - checkout - android/restore-gradle-cache + build_gradle: + description: Build the gradle + steps: + - android/restore-gradle-cache - run: name: Download Dependencies - command: ./gradlew androidDependencies + command: | + sudo chmod +x ./gradlew + ./gradlew androidDependencies - android/save-gradle-cache run_tests: description: run tests for flavour specified @@ -26,14 +32,17 @@ commands: type: string default: "AtlasWeather" steps: - # The next step will run the unit tests - - android/run-tests: - test-command: ./gradlew test<< parameters.flavour >>DebugUnitTest --continue - - store_artifacts: - path: app/build/reports - destination: reports - - store_test_results: - path: app/build/test-results + # The next step will run the unit tests + - build_gradle + - run: + name: Run non-instrumentation unit tests + command: | + ./gradlew test<< parameters.flavour >>DebugUnitTest --continue + - store_artifacts: + path: app/build/reports + destination: reports + - store_test_results: + path: app/build/test-results run_ui_tests: description: run tests for flavour specified parameters: @@ -41,27 +50,44 @@ commands: type: string default: "AtlasWeather" steps: - - android/start-emulator-and-run-tests: - post-emulator-launch-assemble-command: ./gradlew assemble<< parameters.flavour >>DebugAndroidTest - test-command: ./gradlew connected<< parameters.flavour >>DebugAndroidTest - system-image: system-images;android-25;google_apis;x86 - max-tries: 1 - kill-emulators: false - - run: - name: Pull screenshots from device - command: | - mkdir ~/screenshots - adb pull /storage/emulated/0/Android/data/com.appttude.h_mal.atlas_weather/files/screengrab/en-US/images/screenshots ~/screenshots - when: on_fail - # store test reports - - store_artifacts: - path: app/build/reports/androidTests/connected - destination: reports - # store screenshots for failed ui tests - - store_artifacts: - path: ~/screenshots - destination: screenshots - + - build_gradle + - android/start-emulator-and-run-tests: + post-emulator-launch-assemble-command: ./gradlew assemble<< parameters.flavour >>DebugAndroidTest + test-command: ./gradlew connected<< parameters.flavour >>DebugAndroidTest + system-image: system-images;android-25;google_apis;x86 + pull-data: true + pull-data-path: /storage/emulated/0/Android/data/ + pull-data-target: ~/app-data + # store test reports + - store_artifacts: + path: app/build/reports/androidTests/connected + destination: reports + # store screenshots for failed ui tests + - store_artifacts: + path: ~/app-data + destination: screenshots + deploy_to_play_store: + description: deploy to playstore based on flavour + parameters: + flavour: + type: string + default: "AtlasWeather" + steps: + # The next step will run the unit tests + - android/decode-keystore: + keystore-location: "./app/keystore.jks" + - run: + name: Setup playstore key + command: | + echo "$GOOGLE_PLAY_KEY" > "google-play-key.json" + - build_gradle + - run: + name: Run fastlane command to deploy to playstore + command: | + pwd + bundle exec fastlane deploy<< parameters.flavour >> + - store_test_results: + path: fastlane/report.xml # Define a job to be invoked later in a workflow. # See: https://circleci.com/docs/2.0/configuration-reference/#jobs jobs: @@ -83,54 +109,60 @@ jobs: - setup_repo - run_tests: flavour: << parameters.flavour >> - ui-test-and-release: - # Parameters used for determining + - run_ui_tests: + flavour: << parameters.flavour >> + deploy-to-playstore: parameters: flavour: type: string - default: "AtlasWeather" - executor: - name: android/android-machine - tag: 2023.05.1 + default: "Driver" + docker: + - image: cimg/android:2023.07-browsers + auth: + username: ${DOCKER_USERNAME} + password: ${DOCKER_PASSWORD} steps: - setup_repo - - run_ui_tests - - run: - name: Setup variables for release - command: | - echo "$RELEASE_KEYSTORE_BASE64" | base64 --decode > "android/app/release_keystore.jks" - echo "$GOOGLE_PLAY_KEY" > "android/playstore.json" - # And finally run the release build - - run: - name: Assemble and Upload to PlayStore - command: | - pwd - bundle exec fastlane deploy<< parameters.flavour >> + - deploy_to_play_store: + flavour: << parameters.flavour >> # Invoke jobs via workflows # See: https://circleci.com/docs/2.0/configuration-reference/#workflows workflows: version: 2 + build-release-mono: + jobs: + - build-and-test: + context: appttude + flavour: "MonoWeather" + filters: + branches: + ignore: + - main_atlas + - deploy-to-playstore: + context: appttude + flavour: "MonoWeather" + filters: + branches: + only: + - main_mono + requires: + - build-and-test build-release-atlas: jobs: - build-and-test: + context: appttude flavour: "AtlasWeather" - - ui-test-and-release: + filters: + branches: + ignore: + - main_mono + - deploy-to-playstore: + context: appttude flavour: "AtlasWeather" filters: branches: only: - main_atlas - requires: - - build-and-test - build-release-mono: - jobs: - - build-and-test: - flavour: "MonoWeather" - - ui-test-and-release: - flavour: "MonoWeather" - filters: - branches: - only: main_admin requires: - build-and-test \ No newline at end of file diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml index 0c14c02..1d9fb13 100644 --- a/.idea/androidTestResultsUserPreferences.xml +++ b/.idea/androidTestResultsUserPreferences.xml @@ -16,6 +16,19 @@ + + + + + + + @@ -29,6 +42,19 @@ + + + + + + + diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt index 89b4479..2ead089 100644 --- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt +++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt @@ -4,15 +4,19 @@ import android.Manifest import android.app.Activity import android.content.Intent import android.os.Bundle +import android.view.View import androidx.test.core.app.ActivityScenario -import androidx.test.espresso.internal.inject.InstrumentationContext +import androidx.test.espresso.Espresso +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.matcher.ViewMatchers import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import com.appttude.h_mal.atlas_weather.application.TestAppClass -import com.appttude.h_mal.atlas_weather.helper.GenericsHelper.getGenericClassAt import com.appttude.h_mal.atlas_weather.helpers.SnapshotRule import com.appttude.h_mal.atlas_weather.utils.Stubs import kotlinx.coroutines.runBlocking +import org.hamcrest.Matcher import org.junit.After import org.junit.Before import org.junit.Rule @@ -26,6 +30,7 @@ open class BaseTest( lateinit var scenario: ActivityScenario private lateinit var testApp: TestAppClass + private lateinit var testActivity: Activity @get:Rule var permissionRule = GrantPermissionRule.grant(Manifest.permission.ACCESS_COARSE_LOCATION) @@ -36,19 +41,22 @@ open class BaseTest( @Before fun setUp() { Screengrab.setDefaultScreenshotStrategy(UiAutomatorScreenshotStrategy()) - val startIntent = Intent(InstrumentationRegistry.getInstrumentation().targetContext, activity) + val startIntent = + Intent(InstrumentationRegistry.getInstrumentation().targetContext, activity) if (intentBundle != null) { startIntent.replaceExtras(intentBundle) } + testApp = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass + runBlocking { + beforeLaunch() + } + scenario = ActivityScenario.launch(startIntent) scenario.onActivity { - runBlocking { - testApp = it.application as TestAppClass - beforeLaunch() - } + testActivity = it + afterLaunch() } - afterLaunch() } fun stubEndpoint(url: String, stub: Stubs) { @@ -59,6 +67,8 @@ open class BaseTest( testApp.removeUrlStub(url) } + fun getActivity() = testActivity + @After fun tearDown() { testFinished() @@ -67,4 +77,14 @@ open class BaseTest( open fun beforeLaunch() {} open fun afterLaunch() {} open fun testFinished() {} + + fun waitFor(delay: Long) { + Espresso.onView(ViewMatchers.isRoot()).perform(object : ViewAction { + override fun getConstraints(): Matcher = ViewMatchers.isRoot() + override fun getDescription(): String = "wait for $delay milliseconds" + override fun perform(uiController: UiController, v: View?) { + uiController.loopMainThreadForAtLeast(delay) + } + }) + } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/data/location/MockLocationProvider.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/data/location/MockLocationProvider.kt index fb27741..8f36fe7 100644 --- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/data/location/MockLocationProvider.kt +++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/data/location/MockLocationProvider.kt @@ -1,6 +1,5 @@ package com.appttude.h_mal.atlas_weather.data.location -import com.appttude.h_mal.atlas_weather.data.location.LocationProvider import com.appttude.h_mal.atlas_weather.model.types.LocationType class MockLocationProvider : LocationProvider { diff --git a/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/tests/HomePageUITest.kt b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/tests/HomePageUITest.kt index 5b346b3..5e59b4c 100644 --- a/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/tests/HomePageUITest.kt +++ b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/tests/HomePageUITest.kt @@ -7,7 +7,7 @@ import com.appttude.h_mal.atlas_weather.ui.MainActivity import com.appttude.h_mal.atlas_weather.utils.Stubs import org.junit.Test -class HomePageUITest : BaseTest(activity = MainActivity::class.java) { +class HomePageUITest : BaseTest(MainActivity::class.java) { override fun beforeLaunch() { stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Valid) @@ -16,6 +16,7 @@ class HomePageUITest : BaseTest(activity = MainActivity::class.jav @Test fun loadApp_validWeatherResponse_returnsValidPage() { homeScreen { + waitFor(2000) verifyCurrentTemperature(2) verifyCurrentLocation("Mock Location") } diff --git a/app/src/atlasWeather/AndroidManifest.xml b/app/src/atlasWeather/AndroidManifest.xml index bc115db..4ce9d64 100644 --- a/app/src/atlasWeather/AndroidManifest.xml +++ b/app/src/atlasWeather/AndroidManifest.xml @@ -1,8 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> > { - when(it.getContentIfNotHandled()){ - true -> { - progressBar.show() - } - false -> { - progressBar.hide() - } - } - } - - // display a toast when operation fails - fun errorObserver() = Observer> { - it.getContentIfNotHandled()?.let { message -> - displayToast(message) - } - } - - @SuppressLint("MissingPermission") - fun getPermissionResult( - permission: String, - permissionCode: Int, - permissionGranted: () -> Unit - ){ - if (ActivityCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED) { - requestPermissions(arrayOf(permission), permissionCode) - return - }else{ - CoroutineScope(Dispatchers.Main).launch{ - permissionGranted.invoke() - } - } - - } - -} \ No newline at end of file diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/dialog/DeclarationBuilder.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/dialog/DeclarationBuilder.kt new file mode 100644 index 0000000..b2b724f --- /dev/null +++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/dialog/DeclarationBuilder.kt @@ -0,0 +1,22 @@ +package com.appttude.h_mal.atlas_weather.ui.dialog + +import android.content.Context +import android.content.res.Resources +import android.os.Build +import android.text.Html +import androidx.annotation.RequiresApi +import androidx.annotation.StringRes +import androidx.core.content.ContextCompat + +interface DeclarationBuilder{ + val link: String + val message: String + + fun Context.readFromResources(@StringRes id: Int) = resources.getString(id) + + fun buildMessage(): CharSequence? { + val link1 = "here" + val message = "$message See my privacy policy: $link1" + return Html.fromHtml(message, Html.FROM_HTML_MODE_LEGACY) + } +} \ No newline at end of file diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/dialog/PermissionsDeclarationDialog.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/dialog/PermissionsDeclarationDialog.kt new file mode 100644 index 0000000..e1638ca --- /dev/null +++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/dialog/PermissionsDeclarationDialog.kt @@ -0,0 +1,45 @@ +package com.appttude.h_mal.atlas_weather.ui.dialog + +import android.content.Context +import android.text.method.LinkMovementMethod +import android.view.View +import android.widget.TextView +import androidx.appcompat.app.AlertDialog + + +class PermissionsDeclarationDialog(context: Context) : BaseDeclarationDialog(context) { + + override val link: String = "https://sites.google.com/view/hmaldev/home/monochrome" + override val message: String = "Hi, thank you for downloading my app. Google play isn't letting me upload my app to the Playstore until I have a privacy declaration :(. My app is basically used to demonstrate my code=ing to potential employers and others. I do NOT store or process any information. The location permission in the app is there just to provide the end user with weather data." +} + +abstract class BaseDeclarationDialog(val context: Context): DeclarationBuilder { + abstract override val link: String + abstract override val message: String + + lateinit var dialog: AlertDialog + + fun showDialog(agreeCallback: () -> Unit = { }, disagreeCallback: () -> Unit = { }) { + val myMessage = buildMessage() + + val builder = AlertDialog.Builder(context) + .setPositiveButton("agree") { _, _ -> + agreeCallback() + } + .setNegativeButton("disagree") { _, _ -> + disagreeCallback() + } + .setMessage(myMessage) + .setCancelable(false) + + dialog = builder.create() + dialog.show() + + // Make the textview clickable. Must be called after show() + val msgTxt = dialog.findViewById(android.R.id.message) as TextView? + msgTxt?.movementMethod = LinkMovementMethod.getInstance() + } + + fun dismiss() = dialog.dismiss() +} + diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/HomeFragment.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/HomeFragment.kt index 8dbce4c..d61fd7f 100644 --- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/HomeFragment.kt +++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/HomeFragment.kt @@ -1,24 +1,27 @@ package com.appttude.h_mal.atlas_weather.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 -import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem import android.view.View -import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import androidx.lifecycle.observe +import androidx.navigation.Navigation.findNavController +import androidx.navigation.ui.onNavDestinationSelected import androidx.recyclerview.widget.LinearLayoutManager 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.ui.BaseFragment +import com.appttude.h_mal.atlas_weather.model.forecast.Forecast +import com.appttude.h_mal.atlas_weather.ui.dialog.PermissionsDeclarationDialog import com.appttude.h_mal.atlas_weather.ui.home.adapter.WeatherRecyclerAdapter -import com.appttude.h_mal.atlas_weather.utils.displayToast import com.appttude.h_mal.atlas_weather.utils.navigateTo import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory import com.appttude.h_mal.atlas_weather.viewmodel.MainViewModel +import com.appttude.h_mal.monoWeather.ui.BaseFragment import kotlinx.android.synthetic.main.fragment_home.* import org.kodein.di.KodeinAware import org.kodein.di.android.x.kodein @@ -30,43 +33,29 @@ import org.kodein.di.generic.instance * A simple [Fragment] subclass. * create an instance of this fragment. */ -class HomeFragment : BaseFragment(), KodeinAware { - override val kodein by kodein() - private val factory by instance() - - private val viewModel by activityViewModels { factory } - - 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) - } +class HomeFragment : BaseFragment(R.layout.fragment_home) { + private val viewModel by getFragmentViewModel() @SuppressLint("MissingPermission") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + setHasOptionsMenu(true) - val recyclerAdapter = WeatherRecyclerAdapter { - val directions = - HomeFragmentDirections.actionHomeFragmentToFurtherDetailsFragment(it) - navigateTo(directions) - } + val recyclerAdapter = WeatherRecyclerAdapter(itemClick = { + navigateToFurtherDetails(it) + }) forecast_listview.apply { layoutManager = LinearLayoutManager(context) adapter = recyclerAdapter } - getPermissionResult(Manifest.permission.ACCESS_FINE_LOCATION, LOCATION_PERMISSION_REQUEST){ - viewModel.fetchData() - } - swipe_refresh.apply { setOnRefreshListener { - getPermissionResult(Manifest.permission.ACCESS_FINE_LOCATION, LOCATION_PERMISSION_REQUEST){ + getPermissionResult(ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST) { viewModel.fetchData() + isRefreshing = true } - isRefreshing = true } } @@ -76,24 +65,45 @@ class HomeFragment : BaseFragment(), KodeinAware { viewModel.operationState.observe(viewLifecycleOwner, progressBarStateObserver(progressBar)) viewModel.operationError.observe(viewLifecycleOwner, errorObserver()) + viewModel.operationRefresh.observe(viewLifecycleOwner) { it -> + it.getContentIfNotHandled()?.let { + swipe_refresh.isRefreshing = false + } + } - viewModel.operationState.observe(viewLifecycleOwner){ + viewModel.operationState.observe(viewLifecycleOwner) { swipe_refresh.isRefreshing = false } } @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 onStart() { + super.onStart() + + getPermissionResult(ACCESS_COARSE_LOCATION, LOCATION_PERMISSION_REQUEST) { + viewModel.fetchData() } } + + @SuppressLint("MissingPermission") + override fun permissionsGranted() { + viewModel.fetchData() + } + + private fun navigateToFurtherDetails(forecast: Forecast) { + val directions = HomeFragmentDirections + .actionHomeFragmentToFurtherDetailsFragment(forecast) + navigateTo(directions) + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + // Inflate the menu; this adds items to the action bar if it is present. + inflater.inflate(R.menu.menu_main, menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val navController = findNavController(requireActivity(), R.id.container) + return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item) + } } \ No newline at end of file diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/adapter/ViewHolderCurrent.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/adapter/ViewHolderCurrent.kt index 26d5ad6..91a149c 100644 --- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/adapter/ViewHolderCurrent.kt +++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/adapter/ViewHolderCurrent.kt @@ -17,7 +17,7 @@ class ViewHolderCurrent(listItemView: View) : RecyclerView.ViewHolder(listItemVi var tempUnit: TextView = listItemView.findViewById(R.id.temp_unit_4) fun bindData(weather: WeatherDisplay?){ - locationTV.text = weather?.location + locationTV.text = weather?.displayName conditionTV.text = weather?.description weatherIV.loadImage(weather?.iconURL) avgTempTV.text = weather?.averageTemp?.toInt().toString() diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/AddLocationFragment.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/AddLocationFragment.kt index fab3591..663ac99 100644 --- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/AddLocationFragment.kt +++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/AddLocationFragment.kt @@ -7,28 +7,20 @@ import android.view.ViewGroup import androidx.fragment.app.viewModels import androidx.lifecycle.observe import com.appttude.h_mal.atlas_weather.R -import com.appttude.h_mal.atlas_weather.ui.BaseFragment import com.appttude.h_mal.atlas_weather.utils.displayToast import com.appttude.h_mal.atlas_weather.utils.goBack import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel +import com.appttude.h_mal.monoWeather.ui.BaseFragment import kotlinx.android.synthetic.main.activity_add_forecast.* import org.kodein.di.KodeinAware import org.kodein.di.android.x.kodein import org.kodein.di.generic.instance -class AddLocationFragment : BaseFragment(), KodeinAware { - override val kodein by kodein() - private val factory by instance() +class AddLocationFragment : BaseFragment(R.layout.activity_add_forecast) { - private val viewModel by viewModels { factory } - - 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) - } + private val viewModel by getFragmentViewModel() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/WorldFragment.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/WorldFragment.kt index 4171cfa..7fd2d3b 100644 --- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/WorldFragment.kt +++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/WorldFragment.kt @@ -9,12 +9,10 @@ import androidx.fragment.app.viewModels import androidx.lifecycle.observe import androidx.recyclerview.widget.LinearLayoutManager import com.appttude.h_mal.atlas_weather.R -import com.appttude.h_mal.atlas_weather.ui.world.WorldRecyclerAdapter -import com.appttude.h_mal.atlas_weather.ui.BaseFragment -import com.appttude.h_mal.atlas_weather.ui.world.WorldFragmentDirections import com.appttude.h_mal.atlas_weather.utils.navigateTo import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel +import com.appttude.h_mal.monoWeather.ui.BaseFragment import kotlinx.android.synthetic.main.fragment_add_location.* import org.kodein.di.KodeinAware import org.kodein.di.android.x.kodein @@ -25,17 +23,8 @@ import org.kodein.di.generic.instance * A simple [Fragment] subclass. * create an instance of this fragment. */ -class WorldFragment : BaseFragment(), KodeinAware { - override val kodein by kodein() - private val factory by instance() - - val viewModel by viewModels { factory } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_add_location, container, false) - } +class WorldFragment : BaseFragment(R.layout.fragment_add_location) { + val viewModel by getFragmentViewModel() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/atlasWeather/res/drawable/gradient.xml b/app/src/atlasWeather/res/drawable/gradient.xml new file mode 100644 index 0000000..8c3b3d7 --- /dev/null +++ b/app/src/atlasWeather/res/drawable/gradient.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/atlasWeather/res/font/archeologicaps.ttf b/app/src/atlasWeather/res/font/archeologicaps.ttf new file mode 100644 index 0000000..c245135 Binary files /dev/null and b/app/src/atlasWeather/res/font/archeologicaps.ttf differ diff --git a/app/src/atlasWeather/res/layout/list_item_current.xml b/app/src/atlasWeather/res/layout/list_item_current.xml index e816d27..55a3040 100644 --- a/app/src/atlasWeather/res/layout/list_item_current.xml +++ b/app/src/atlasWeather/res/layout/list_item_current.xml @@ -76,7 +76,7 @@ android:id="@+id/icon_main_4" android:layout_width="64dp" android:layout_height="64dp" - tools:src="@drawable/day_305" /> + tools:srcCompat="@drawable/water_drop" /> + android:adjustViewBounds="true" + tools:layout_width="32dp" + tools:srcCompat="@drawable/water_drop" /> + \ No newline at end of file diff --git a/app/src/atlasWeather/res/values/colors.xml b/app/src/atlasWeather/res/values/colors.xml new file mode 100644 index 0000000..64f6f5e --- /dev/null +++ b/app/src/atlasWeather/res/values/colors.xml @@ -0,0 +1,12 @@ + + + #3F51B5 + #303F9F + #FF4081 + + #E8D0DD + #5F8E7B + #B3C0CA + #8C98AD + #2E3532 + diff --git a/app/src/atlasWeather/res/values/styles.xml b/app/src/atlasWeather/res/values/styles.xml index 9fcabf4..d984b59 100644 --- a/app/src/atlasWeather/res/values/styles.xml +++ b/app/src/atlasWeather/res/values/styles.xml @@ -3,24 +3,27 @@ @@ -42,12 +45,4 @@ 32sp - - - + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 470b20c..4e5c178 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,6 +7,8 @@ + + diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/data/location/LocationProviderImpl.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/data/location/LocationProviderImpl.kt index 194aeec..652c13c 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/data/location/LocationProviderImpl.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/data/location/LocationProviderImpl.kt @@ -26,7 +26,7 @@ import kotlin.coroutines.suspendCoroutine class LocationProviderImpl( private val applicationContext: Context -) : com.appttude.h_mal.atlas_weather.data.location.LocationProvider, com.appttude.h_mal.atlas_weather.data.location.LocationHelper(applicationContext) { +) : LocationProvider, LocationHelper(applicationContext) { private var locationManager = applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager? private val client = FusedLocationProviderClient(applicationContext) diff --git a/app/src/monoWeather/java/com/appttude/h_mal/monoWeather/ui/BaseFragment.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/ui/BaseFragment.kt similarity index 100% rename from app/src/monoWeather/java/com/appttude/h_mal/monoWeather/ui/BaseFragment.kt rename to app/src/main/java/com/appttude/h_mal/atlas_weather/ui/BaseFragment.kt diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index be1d7e9..3fee5a4 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -26,7 +26,7 @@ android:layout_height="match_parent" android:background="@android:color/black" android:visibility="gone" - tools:visibility="visible"> + tools:visibility="gone"> #ffffff 12sp + + \ No newline at end of file diff --git a/app/src/monoWeather/AndroidManifest.xml b/app/src/monoWeather/AndroidManifest.xml index 490aa84..37c80ec 100644 --- a/app/src/monoWeather/AndroidManifest.xml +++ b/app/src/monoWeather/AndroidManifest.xml @@ -2,9 +2,6 @@ - - - 32sp - - diff --git a/fastlane/Appfile b/fastlane/Appfile deleted file mode 100644 index 2636069..0000000 --- a/fastlane/Appfile +++ /dev/null @@ -1,2 +0,0 @@ -json_key_file("") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one -package_name("") # e.g. com.krausefx.app diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 19c557c..54d6de6 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -16,23 +16,30 @@ default_platform(:android) platform :android do - desc "Runs all the tests" - lane :test do - gradle(task: "test") + + desc "Deploy a new Mono Weather version to the Google Play" + lane :deployMono do + gradle( + task: "clean bundle", + flavor: "MonoWeather", + build_type: "Release", + ) + upload_to_play_store( + aab: "app/build/outputs/bundle/monoWeather/app-driver-release.aab", + json_key: "google-play-key.json", + package_name: "h_mal.appttude.com.monoWeather") end - desc "Submit a new Beta Build to Crashlytics Beta" - lane :beta do - gradle(task: "clean assembleRelease") - crashlytics - - # sh "your_script.sh" - # You can also use other beta testing services here - end - - desc "Deploy a new version to the Google Play" - lane :deploy do - gradle(task: "clean assembleRelease") - upload_to_play_store + desc "Deploy a new Atlas Weather version to the Google Play" + lane :deployMono do + gradle( + task: "clean bundle", + flavor: "AtlasWeather", + build_type: "Release", + ) + upload_to_play_store( + aab: "app/build/outputs/bundle/atlasWeather/app-driver-release.aab", + json_key: "google-play-key.json", + package_name: "h_mal.appttude.com.monoWeather") end end