- Code inspection

- Redundant resources removed
 - Resources moved the corresponding flavours
 - Deprecated dependencies upgraded
 - lint changes
This commit is contained in:
2023-08-08 22:20:39 +01:00
parent 9189a4412d
commit 9a0189c8ec
174 changed files with 1359 additions and 1245 deletions

View File

@@ -30,7 +30,7 @@ android {
} }
} }
android { android {
sourceSets{ sourceSets {
test { test {
resources.srcDirs += ['src/test/resources'] resources.srcDirs += ['src/test/resources']
} }
@@ -96,32 +96,30 @@ android {
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.2.1' implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0' implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation "com.google.android.gms:play-services-location:18.0.0" implementation "com.google.android.gms:play-services-location:21.0.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.cardview:cardview:1.0.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
implementation 'androidx.preference:preference:1.2.1'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.1'
/ * Fragment Navigation * /
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2' implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2'
implementation 'androidx.navigation:navigation-ui-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'
implementation 'androidx.preference:preference:1.2.1'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
/ * Unit testing * / / * Unit testing * /
testImplementation 'junit:junit:4.13' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
/ * android unit testing and espresso * / / * android unit testing and espresso * /
androidTestImplementation 'androidx.test:rules:1.4.1-alpha06' androidTestImplementation 'androidx.test:rules:1.5.0'
androidTestImplementation "androidx.test:core:1.4.0" androidTestImplementation "androidx.test:core:1.5.0"
/ * Android Espresso * / / * Android Espresso * /
def testJunitVersion = "1.1.5" def testJunitVersion = "1.1.5"
@@ -149,13 +147,13 @@ dependencies {
androidTestImplementation "io.mockk:mockk-android:$mockk_ver" androidTestImplementation "io.mockk:mockk-android:$mockk_ver"
/ * Retrofit * / / * Retrofit * /
def retrofit_ver = "2.8.1" def retrofit_ver = "2.9.0"
implementation "com.squareup.retrofit2:retrofit:$retrofit_ver" implementation "com.squareup.retrofit2:retrofit:$retrofit_ver"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_ver" implementation "com.squareup.retrofit2:converter-gson:$retrofit_ver"
implementation "com.squareup.okhttp3:logging-interceptor:4.9.0" implementation "com.squareup.okhttp3:logging-interceptor:4.9.0"
/ * Shared prefs * / / * Shared prefs * /
def prefs_ver = "1.1.1" def prefs_ver = "1.2.0"
implementation "androidx.preference:preference-ktx:$prefs_ver" implementation "androidx.preference:preference-ktx:$prefs_ver"
/ *Kodein Dependency Injection * / / *Kodein Dependency Injection * /
@@ -164,7 +162,7 @@ dependencies {
implementation "org.kodein.di:kodein-di-framework-android-x:$kodein_version" implementation "org.kodein.di:kodein-di-framework-android-x:$kodein_version"
/ * Room database * / / * Room database * /
def room_version = "2.3.0-alpha03" def room_version = "2.4.3"
implementation "androidx.room:room-runtime:$room_version" implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version" kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version" implementation "androidx.room:room-ktx:$room_version"
@@ -182,7 +180,7 @@ dependencies {
implementation "com.tomtom.online:sdk-maps:2.4807" implementation "com.tomtom.online:sdk-maps:2.4807"
/ * coroutines support for firebase operations * / / * coroutines support for firebase operations * /
def coroutines_google_ver = "1.1.1" def coroutines_google_ver = "1.6.4"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutines_google_ver" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutines_google_ver"
/ * Picasso * / / * Picasso * /

View File

@@ -1,3 +1,5 @@
@file:Suppress("EmptyMethod")
package com.appttude.h_mal.atlas_weather package com.appttude.h_mal.atlas_weather
import android.Manifest import android.Manifest
@@ -23,6 +25,7 @@ import org.junit.Rule
import tools.fastlane.screengrab.Screengrab import tools.fastlane.screengrab.Screengrab
import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy
@Suppress("EmptyMethod")
open class BaseTest<A : Activity>( open class BaseTest<A : Activity>(
private val activity: Class<A>, private val activity: Class<A>,
private val intentBundle: Bundle? = null, private val intentBundle: Bundle? = null,
@@ -47,7 +50,8 @@ open class BaseTest<A : Activity>(
startIntent.replaceExtras(intentBundle) startIntent.replaceExtras(intentBundle)
} }
testApp = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass testApp =
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass
runBlocking { runBlocking {
beforeLaunch() beforeLaunch()
} }

View File

@@ -17,9 +17,9 @@ import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.PickerActions import androidx.test.espresso.contrib.PickerActions
import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.espresso.matcher.ViewMatchers.*
import com.appttude.h_mal.atlas_weather.helpers.EspressoHelper.waitForView
import com.appttude.h_mal.atlas_weather.helpers.checkErrorMessage import com.appttude.h_mal.atlas_weather.helpers.checkErrorMessage
import com.appttude.h_mal.atlas_weather.helpers.checkImage import com.appttude.h_mal.atlas_weather.helpers.checkImage
import com.appttude.h_mal.atlas_weather.helpers.EspressoHelper.waitForView
import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.anything import org.hamcrest.CoreMatchers.anything
import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.CoreMatchers.equalTo
@@ -138,7 +138,7 @@ open class BaseTestRobot {
fun getStringFromResource(@StringRes resId: Int): String = fun getStringFromResource(@StringRes resId: Int): String =
Resources.getSystem().getString(resId) Resources.getSystem().getString(resId)
fun pullToRefresh(resId: Int){ fun pullToRefresh(resId: Int) {
onView(allOf(withId(resId), isDisplayed())).perform(swipeDown()) onView(allOf(withId(resId), isDisplayed())).perform(swipeDown())
} }

View File

@@ -8,7 +8,11 @@ class MockLocationProvider : LocationProvider {
override suspend fun getCurrentLatLong() = latLong override suspend fun getCurrentLatLong() = latLong
override fun getLatLongFromLocationName(location: String) = latLong override fun getLatLongFromLocationName(location: String) = latLong
override suspend fun getLocationNameFromLatLong(lat: Double, long: Double, type: LocationType): String { override suspend fun getLocationNameFromLatLong(
lat: Double,
long: Double,
type: LocationType
): String {
return "Mock Location" return "Mock Location"
} }

View File

@@ -4,7 +4,7 @@ import android.view.View
import org.hamcrest.BaseMatcher import org.hamcrest.BaseMatcher
import org.hamcrest.Description import org.hamcrest.Description
class BaseMatcher: BaseMatcher<View>() { class BaseMatcher : BaseMatcher<View>() {
override fun describeTo(description: Description?) { override fun describeTo(description: Description?) {
TODO("Not yet implemented") TODO("Not yet implemented")
} }

View File

@@ -6,7 +6,8 @@ import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom
import org.hamcrest.Matcher import org.hamcrest.Matcher
open class BaseViewAction: ViewAction { @Suppress("EmptyMethod")
open class BaseViewAction : ViewAction {
override fun getDescription(): String? = setDescription() override fun getDescription(): String? = setDescription()
override fun getConstraints(): Matcher<View> = setConstraints() override fun getConstraints(): Matcher<View> = setConstraints()
@@ -15,13 +16,11 @@ open class BaseViewAction: ViewAction {
setPerform(uiController, view) setPerform(uiController, view)
} }
open fun setDescription(): String? { open fun setDescription(): String? = ""
return null
}
open fun setConstraints(): Matcher<View> { open fun setConstraints(): Matcher<View> {
return isAssignableFrom(View::class.java) return isAssignableFrom(View::class.java)
} }
open fun setPerform(uiController: UiController?, view: View?) { } open fun setPerform(uiController: UiController?, view: View?) {}
} }

View File

@@ -36,7 +36,7 @@ object EspressoHelper {
var tries = 0 var tries = 0
val childViews: Iterable<View> = TreeIterables.breadthFirstViewTraversal(view) val childViews: Iterable<View> = TreeIterables.breadthFirstViewTraversal(view)
// Look for the match in the tree of childviews // Look for the match in the tree of child views
childViews.forEach { childViews.forEach {
tries++ tries++
if (viewMatcher.matches(it)) { if (viewMatcher.matches(it)) {

View File

@@ -14,6 +14,9 @@ class SnapshotRule : TestWatcher() {
} }
fun getScreenshotName(description: Description): String { fun getScreenshotName(description: Description): String {
return description.className.replace(".", "-") + "_" + description.methodName.replace(".", "-") return description.className.replace(".", "-") + "_" + description.methodName.replace(
".",
"-"
)
} }
} }

View File

@@ -3,7 +3,7 @@ package com.appttude.h_mal.atlas_weather.utils
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
class DateUtilsKtTest{ class DateUtilsKtTest {
@Test @Test
fun toDayString_testStandardData_outputCorrect() { fun toDayString_testStandardData_outputCorrect() {

View File

@@ -5,7 +5,9 @@ import com.appttude.h_mal.atlas_weather.R
fun homeScreen(func: HomeScreenRobot.() -> Unit) = HomeScreenRobot().apply { func() } fun homeScreen(func: HomeScreenRobot.() -> Unit) = HomeScreenRobot().apply { func() }
class HomeScreenRobot : BaseTestRobot() { class HomeScreenRobot : BaseTestRobot() {
fun verifyCurrentTemperature(temperature: Int) = matchText(R.id.temp_main_4, temperature.toString()) fun verifyCurrentTemperature(temperature: Int) =
matchText(R.id.temp_main_4, temperature.toString())
fun verifyCurrentLocation(location: String) = matchText(R.id.location_main_4, location) fun verifyCurrentLocation(location: String) = matchText(R.id.location_main_4, location)
fun refresh() = pullToRefresh(R.id.swipe_refresh) fun refresh() = pullToRefresh(R.id.swipe_refresh)
} }

View File

@@ -8,7 +8,7 @@ import androidx.test.espresso.matcher.ViewMatchers
import com.appttude.h_mal.atlas_weather.BaseTest import com.appttude.h_mal.atlas_weather.BaseTest
import com.appttude.h_mal.atlas_weather.ui.MainActivity import com.appttude.h_mal.atlas_weather.ui.MainActivity
open class MonoBaseTest: BaseTest<MainActivity>(MainActivity::class.java) { open class MonoBaseTest : BaseTest<MainActivity>(MainActivity::class.java) {
override fun afterLaunch() { override fun afterLaunch() {
// Dismiss dialog on start up // Dismiss dialog on start up

View File

@@ -1,11 +1,13 @@
package com.appttude.h_mal.monoWeather.robot package com.appttude.h_mal.monoWeather.robot
import com.appttude.h_mal.atlas_weather.R
import com.appttude.h_mal.atlas_weather.BaseTestRobot import com.appttude.h_mal.atlas_weather.BaseTestRobot
import com.appttude.h_mal.atlas_weather.R
fun homeScreen(func: HomeScreenRobot.() -> Unit) = HomeScreenRobot().apply { func() } fun homeScreen(func: HomeScreenRobot.() -> Unit) = HomeScreenRobot().apply { func() }
class HomeScreenRobot : BaseTestRobot() { class HomeScreenRobot : BaseTestRobot() {
fun verifyCurrentTemperature(temperature: Int) = matchText(R.id.temp_main_4, temperature.toString()) fun verifyCurrentTemperature(temperature: Int) =
matchText(R.id.temp_main_4, temperature.toString())
fun verifyCurrentLocation(location: String) = matchText(R.id.location_main_4, location) fun verifyCurrentLocation(location: String) = matchText(R.id.location_main_4, location)
fun refresh() = pullToRefresh(R.id.swipe_refresh) fun refresh() = pullToRefresh(R.id.swipe_refresh)
} }

View File

@@ -1,7 +1,7 @@
package com.appttude.h_mal.monoWeather.robot package com.appttude.h_mal.monoWeather.robot
import com.appttude.h_mal.atlas_weather.R
import com.appttude.h_mal.atlas_weather.BaseTestRobot import com.appttude.h_mal.atlas_weather.BaseTestRobot
import com.appttude.h_mal.atlas_weather.R
fun widgetPermissionScreen(func: WidgetPermissionScreenRobot.() -> Unit) = fun widgetPermissionScreen(func: WidgetPermissionScreenRobot.() -> Unit) =
WidgetPermissionScreenRobot().apply { func() } WidgetPermissionScreenRobot().apply { func() }

View File

@@ -1,10 +1,11 @@
package com.appttude.h_mal.monoWeather.tests package com.appttude.h_mal.monoWeather.tests
import com.appttude.h_mal.monoWeather.robot.homeScreen 00import com.appttude.h_mal.atlas_weather.utils.Stubs
import com.appttude.h_mal.atlas_weather.utils.Stubs
import com.appttude.h_mal.monoWeather.MonoBaseTest import com.appttude.h_mal.monoWeather.MonoBaseTest
import com.appttude.h_mal.monoWeather.robot.homeScreen
import org.junit.Test import org.junit.Test
import java.io.IOException
class HomePageUITest : MonoBaseTest() { class HomePageUITest : MonoBaseTest() {
@@ -18,5 +19,6 @@ class HomePageUITest : MonoBaseTest() {
verifyCurrentTemperature(2) verifyCurrentTemperature(2)
verifyCurrentLocation("Mock Location") verifyCurrentLocation("Mock Location")
} }
throw IOException("sdfsdfasdfasdfasdf")
} }
} }

View File

@@ -1,9 +1,7 @@
package com.appttude.h_mal.monoWeather.tests package com.appttude.h_mal.monoWeather.tests
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.test.rule.ActivityTestRule
import com.appttude.h_mal.atlas_weather.BaseTest import com.appttude.h_mal.atlas_weather.BaseTest
import com.appttude.h_mal.monoWeather.robot.widgetPermissionScreen import com.appttude.h_mal.monoWeather.robot.widgetPermissionScreen
import com.appttude.h_mal.monoWeather.ui.widget.WidgetLocationPermissionActivity import com.appttude.h_mal.monoWeather.ui.widget.WidgetLocationPermissionActivity

View File

@@ -12,11 +12,12 @@
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
tools:node="merge"> tools:node="merge">
<activity android:name=".ui.MainActivity" <activity
android:name=".ui.MainActivity"
android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/AppTheme.NoActionBar" android:theme="@style/AppTheme.NoActionBar">
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
@@ -24,12 +25,14 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<receiver <receiver
android:name=".notification.NotificationReceiver" android:name=".notification.NotificationReceiver"
android:parentActivityName=".MainActivity" android:exported="true"
android:exported="true"/> android:parentActivityName=".MainActivity" />
<receiver android:name=".widget.NewAppWidget" <receiver
android:name=".widget.NewAppWidget"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

View File

@@ -34,7 +34,11 @@ class NotificationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
kodein.baseKodein = (context.applicationContext as KodeinAware).kodein kodein.baseKodein = (context.applicationContext as KodeinAware).kodein
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
context.displayToast("Please enable location permissions") context.displayToast("Please enable location permissions")
return return
} }
@@ -52,11 +56,7 @@ class NotificationReceiver : BroadcastReceiver() {
val pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT) val pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
val builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val builder = Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
} else {
Notification.Builder(context)
}
val notification = builder.setContentTitle("Weather App") val notification = builder.setContentTitle("Weather App")
.setContentText(weather.current?.main + "°C") .setContentText(weather.current?.main + "°C")
@@ -64,10 +64,9 @@ class NotificationReceiver : BroadcastReceiver() {
// .setLargeIcon(Icon.createWithResource(context, getImageResource(forecastItem.getCurrentForecast().getIconURL(), context))) // .setLargeIcon(Icon.createWithResource(context, getImageResource(forecastItem.getCurrentForecast().getIconURL(), context)))
.setAutoCancel(true) .setAutoCancel(true)
.setContentIntent(pendingIntent).build() .setContentIntent(pendingIntent).build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(NOTIFICATION_CHANNEL_ID) builder.setChannelId(NOTIFICATION_CHANNEL_ID)
} val notificationManager =
val notificationManager = context!!.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager context!!.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(0, notification) notificationManager.notify(0, notification)
} }
} }

View File

@@ -2,7 +2,7 @@ package com.appttude.h_mal.atlas_weather.ui
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
abstract class BaseActivity : AppCompatActivity(){ abstract class BaseActivity : AppCompatActivity() {
} }

View File

@@ -21,8 +21,10 @@ class WorldItemFragment : Fragment() {
param1 = WorldItemFragmentArgs.fromBundle(requireArguments()).weatherDisplay param1 = WorldItemFragmentArgs.fromBundle(requireArguments()).weatherDisplay
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, override fun onCreateView(
savedInstanceState: Bundle?): View? { inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false) return inflater.inflate(R.layout.fragment_home, container, false)
} }

View File

@@ -11,6 +11,7 @@ import kotlinx.android.synthetic.main.activity_further_info.*
private const val WEATHER = "param1" private const val WEATHER = "param1"
/** /**
* A simple [Fragment] subclass. * A simple [Fragment] subclass.
* Use the [FurtherInfoFragment.newInstance] factory method to * Use the [FurtherInfoFragment.newInstance] factory method to
@@ -24,7 +25,11 @@ class FurtherInfoFragment : Fragment() {
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.activity_further_info, container, false) return inflater.inflate(R.layout.activity_further_info, container, false)
} }

View File

@@ -8,7 +8,7 @@ import androidx.annotation.RequiresApi
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
interface DeclarationBuilder{ interface DeclarationBuilder {
val link: String val link: String
val message: String val message: String

View File

@@ -10,10 +10,11 @@ import androidx.appcompat.app.AlertDialog
class PermissionsDeclarationDialog(context: Context) : BaseDeclarationDialog(context) { class PermissionsDeclarationDialog(context: Context) : BaseDeclarationDialog(context) {
override val link: String = "https://sites.google.com/view/hmaldev/home/monochrome" 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." 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 class BaseDeclarationDialog(val context: Context) : DeclarationBuilder {
abstract override val link: String abstract override val link: String
abstract override val message: String abstract override val message: String

View File

@@ -3,4 +3,4 @@ package com.appttude.h_mal.atlas_weather.ui.home.adapter
import android.view.View import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
class EmptyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) class EmptyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

View File

@@ -16,7 +16,7 @@ class ViewHolderCurrent(listItemView: View) : RecyclerView.ViewHolder(listItemVi
var avgTempTV: TextView = listItemView.findViewById(R.id.temp_main_4) var avgTempTV: TextView = listItemView.findViewById(R.id.temp_main_4)
var tempUnit: TextView = listItemView.findViewById(R.id.temp_unit_4) var tempUnit: TextView = listItemView.findViewById(R.id.temp_unit_4)
fun bindData(weather: WeatherDisplay?){ fun bindData(weather: WeatherDisplay?) {
locationTV.text = weather?.displayName locationTV.text = weather?.displayName
conditionTV.text = weather?.description conditionTV.text = weather?.description
weatherIV.loadImage(weather?.iconURL) weatherIV.loadImage(weather?.iconURL)

View File

@@ -14,7 +14,7 @@ internal class ViewHolderFurtherDetails(itemView: View) : RecyclerView.ViewHolde
var humidity: TextView = itemView.findViewById(R.id.humidity_) var humidity: TextView = itemView.findViewById(R.id.humidity_)
var clouds: TextView = itemView.findViewById(R.id.clouds_) var clouds: TextView = itemView.findViewById(R.id.clouds_)
fun bindData(weather: WeatherDisplay?){ fun bindData(weather: WeatherDisplay?) {
windSpeed.text = weather?.windSpeed windSpeed.text = weather?.windSpeed
windDirection.text = weather?.windDirection windDirection.text = weather?.windDirection
precipitation.text = weather?.precipitation precipitation.text = weather?.precipitation

View File

@@ -15,25 +15,28 @@ class WeatherRecyclerAdapter(
var weather: WeatherDisplay? = null var weather: WeatherDisplay? = null
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
fun addCurrent(current: WeatherDisplay){ fun addCurrent(current: WeatherDisplay) {
weather = current weather = current
notifyDataSetChanged() notifyDataSetChanged()
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (getDataType(viewType)){ return when (getDataType(viewType)) {
is ViewType.Empty -> { is ViewType.Empty -> {
val emptyViewHolder = View(parent.context) val emptyViewHolder = View(parent.context)
EmptyViewHolder(emptyViewHolder) EmptyViewHolder(emptyViewHolder)
} }
is ViewType.Current -> { is ViewType.Current -> {
val viewCurrent = parent.generateView(R.layout.list_item_current) val viewCurrent = parent.generateView(R.layout.list_item_current)
ViewHolderCurrent(viewCurrent) ViewHolderCurrent(viewCurrent)
} }
is ViewType.Forecast -> { is ViewType.Forecast -> {
val viewForecast = parent.generateView(R.layout.list_item_forecast) val viewForecast = parent.generateView(R.layout.list_item_forecast)
ViewHolderForecast(viewForecast) ViewHolderForecast(viewForecast)
} }
is ViewType.Further -> { is ViewType.Further -> {
val viewFurther = parent.generateView(R.layout.list_item_further) val viewFurther = parent.generateView(R.layout.list_item_further)
ViewHolderFurtherDetails(viewFurther) ViewHolderFurtherDetails(viewFurther)
@@ -41,7 +44,7 @@ class WeatherRecyclerAdapter(
} }
} }
sealed class ViewType{ sealed class ViewType {
object Empty : ViewType() object Empty : ViewType()
object Current : ViewType() object Current : ViewType()
object Forecast : ViewType() object Forecast : ViewType()
@@ -49,7 +52,7 @@ class WeatherRecyclerAdapter(
} }
private fun getDataType(type: Int): ViewType { private fun getDataType(type: Int): ViewType {
return when (type){ return when (type) {
0 -> ViewType.Empty 0 -> ViewType.Empty
1 -> ViewType.Current 1 -> ViewType.Current
2 -> ViewType.Forecast 2 -> ViewType.Forecast
@@ -61,23 +64,25 @@ class WeatherRecyclerAdapter(
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
if (weather == null) return 0 if (weather == null) return 0
return when(position){ return when (position) {
0 -> 1 0 -> 1
in 1 until itemCount -2 -> 2 in 1 until itemCount - 2 -> 2
itemCount - 1 -> 3 itemCount - 1 -> 3
else -> 0 else -> 0
} }
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (getDataType(getItemViewType(position))){ when (getDataType(getItemViewType(position))) {
is ViewType.Empty -> { is ViewType.Empty -> {
holder as EmptyViewHolder holder as EmptyViewHolder
} }
is ViewType.Current -> { is ViewType.Current -> {
val viewHolderCurrent = holder as ViewHolderCurrent val viewHolderCurrent = holder as ViewHolderCurrent
viewHolderCurrent.bindData(weather) viewHolderCurrent.bindData(weather)
} }
is ViewType.Forecast -> { is ViewType.Forecast -> {
val viewHolderForecast = holder as ViewHolderForecast val viewHolderForecast = holder as ViewHolderForecast
@@ -88,6 +93,7 @@ class WeatherRecyclerAdapter(
} }
} }
} }
is ViewType.Further -> { is ViewType.Further -> {
val viewHolderCurrent = holder as ViewHolderFurtherDetails val viewHolderCurrent = holder as ViewHolderFurtherDetails
viewHolderCurrent.bindData(weather) viewHolderCurrent.bindData(weather)
@@ -98,7 +104,7 @@ class WeatherRecyclerAdapter(
override fun getItemCount(): Int { override fun getItemCount(): Int {
if (weather == null) return 0 if (weather == null) return 0
return 2 + (weather?.forecast?.size?: 0) return 2 + (weather?.forecast?.size ?: 0)
} }
} }

View File

@@ -34,11 +34,16 @@ class SettingsFragment : PreferenceFragmentCompat() {
setupNotificationBroadcaster(requireContext()) setupNotificationBroadcaster(requireContext())
} }
if (key == "widget_black_background"){ if (key == "widget_black_background") {
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE) val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
val widgetManager = AppWidgetManager.getInstance(requireContext()) val widgetManager = AppWidgetManager.getInstance(requireContext())
val ids = val ids =
widgetManager.getAppWidgetIds(ComponentName(requireContext(), NewAppWidget::class.java)) widgetManager.getAppWidgetIds(
ComponentName(
requireContext(),
NewAppWidget::class.java
)
)
AppWidgetManager.getInstance(requireContext()) AppWidgetManager.getInstance(requireContext())
.notifyAppWidgetViewDataChanged(ids, R.id.whole_widget_view) .notifyAppWidgetViewDataChanged(ids, R.id.whole_widget_view)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids) intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
@@ -50,12 +55,19 @@ class SettingsFragment : PreferenceFragmentCompat() {
fun setupNotificationBroadcaster(context: Context) { fun setupNotificationBroadcaster(context: Context) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val notificationIntent = Intent(context, NotificationReceiver::class.java) val notificationIntent = Intent(context, NotificationReceiver::class.java)
val broadcast = PendingIntent.getBroadcast(context, 100, notificationIntent, val broadcast = PendingIntent.getBroadcast(
PendingIntent.FLAG_UPDATE_CURRENT) context, 100, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
val cal: Calendar = Calendar.getInstance() val cal: Calendar = Calendar.getInstance()
cal.set(Calendar.HOUR_OF_DAY, 6) cal.set(Calendar.HOUR_OF_DAY, 6)
cal.set(Calendar.MINUTE, 8) cal.set(Calendar.MINUTE, 8)
cal.set(Calendar.SECOND, 5) cal.set(Calendar.SECOND, 5)
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.timeInMillis, AlarmManager.INTERVAL_DAY, broadcast) alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
cal.timeInMillis,
AlarmManager.INTERVAL_DAY,
broadcast
)
} }
} }

View File

@@ -27,7 +27,7 @@ class AddLocationFragment : BaseFragment(R.layout.activity_add_forecast) {
submit.setOnClickListener { submit.setOnClickListener {
val locationName = location_name_tv.text?.trim()?.toString() val locationName = location_name_tv.text?.trim()?.toString()
if (locationName.isNullOrBlank()){ if (locationName.isNullOrBlank()) {
submit.error = "Location cannot be blank" submit.error = "Location cannot be blank"
return@setOnClickListener return@setOnClickListener
} }
@@ -38,7 +38,7 @@ class AddLocationFragment : BaseFragment(R.layout.activity_add_forecast) {
viewModel.operationError.observe(viewLifecycleOwner, errorObserver()) viewModel.operationError.observe(viewLifecycleOwner, errorObserver())
viewModel.operationComplete.observe(viewLifecycleOwner) { viewModel.operationComplete.observe(viewLifecycleOwner) {
it?.getContentIfNotHandled()?.let {message -> it?.getContentIfNotHandled()?.let { message ->
displayToast(message) displayToast(message)
} }
goBack() goBack()

View File

@@ -1,22 +1,17 @@
package com.appttude.h_mal.atlas_weather.ui.world package com.appttude.h_mal.atlas_weather.ui.world
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.observe import androidx.lifecycle.observe
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.appttude.h_mal.atlas_weather.R import com.appttude.h_mal.atlas_weather.R
import com.appttude.h_mal.atlas_weather.utils.navigateTo 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.atlas_weather.viewmodel.WorldViewModel
import com.appttude.h_mal.monoWeather.ui.BaseFragment import com.appttude.h_mal.monoWeather.ui.BaseFragment
import kotlinx.android.synthetic.main.fragment_add_location.* import kotlinx.android.synthetic.atlasWeather.fragment_add_location.floatingActionButton
import org.kodein.di.KodeinAware import kotlinx.android.synthetic.atlasWeather.fragment_add_location.progressBar2
import org.kodein.di.android.x.kodein import kotlinx.android.synthetic.atlasWeather.fragment_add_location.world_recycler
import org.kodein.di.generic.instance
/** /**
@@ -29,7 +24,7 @@ class WorldFragment : BaseFragment(R.layout.fragment_add_location) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val recyclerAdapter = WorldRecyclerAdapter{ val recyclerAdapter = WorldRecyclerAdapter {
val direction = val direction =
WorldFragmentDirections.actionWorldFragmentToWorldItemFragment(it) WorldFragmentDirections.actionWorldFragmentToWorldItemFragment(it)
navigateTo(direction) navigateTo(direction)
@@ -44,7 +39,7 @@ class WorldFragment : BaseFragment(R.layout.fragment_add_location) {
recyclerAdapter.addCurrent(it) recyclerAdapter.addCurrent(it)
} }
floatingActionButton.setOnClickListener{ floatingActionButton.setOnClickListener {
navigateTo(R.id.action_worldFragment_to_addLocationFragment) navigateTo(R.id.action_worldFragment_to_addLocationFragment)
} }

View File

@@ -15,18 +15,19 @@ class WorldRecyclerAdapter(
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var weather: MutableList<WeatherDisplay> = mutableListOf() var weather: MutableList<WeatherDisplay> = mutableListOf()
fun addCurrent(current: List<WeatherDisplay>){ fun addCurrent(current: List<WeatherDisplay>) {
weather.clear() weather.clear()
weather.addAll(current) weather.addAll(current)
notifyDataSetChanged() notifyDataSetChanged()
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (getDataType(viewType)){ return when (getDataType(viewType)) {
is ViewType.Empty -> { is ViewType.Empty -> {
val emptyViewHolder = View(parent.context) val emptyViewHolder = View(parent.context)
EmptyViewHolder(emptyViewHolder) EmptyViewHolder(emptyViewHolder)
} }
is ViewType.Current -> { is ViewType.Current -> {
val viewCurrent = parent.generateView(R.layout.db_list_item) val viewCurrent = parent.generateView(R.layout.db_list_item)
WorldHolderCurrent(viewCurrent) WorldHolderCurrent(viewCurrent)
@@ -34,13 +35,13 @@ class WorldRecyclerAdapter(
} }
} }
sealed class ViewType{ sealed class ViewType {
object Empty : ViewType() object Empty : ViewType()
object Current : ViewType() object Current : ViewType()
} }
private fun getDataType(type: Int): ViewType{ private fun getDataType(type: Int): ViewType {
return when (type){ return when (type) {
0 -> ViewType.Empty 0 -> ViewType.Empty
1 -> ViewType.Current 1 -> ViewType.Current
else -> ViewType.Empty else -> ViewType.Empty
@@ -52,11 +53,12 @@ class WorldRecyclerAdapter(
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (getDataType(getItemViewType(position))){ when (getDataType(getItemViewType(position))) {
is ViewType.Empty -> { is ViewType.Empty -> {
holder as EmptyViewHolder holder as EmptyViewHolder
} }
is ViewType.Current -> { is ViewType.Current -> {
val viewHolderCurrent = holder as WorldHolderCurrent val viewHolderCurrent = holder as WorldHolderCurrent
viewHolderCurrent.bindData(weather[position]) viewHolderCurrent.bindData(weather[position])
@@ -79,7 +81,7 @@ class WorldRecyclerAdapter(
var avgTempTV: TextView = listItemView.findViewById(R.id.db_main_temp) var avgTempTV: TextView = listItemView.findViewById(R.id.db_main_temp)
// var tempUnit: TextView = listItemView.findViewById(R.id.db_minor_temp) // var tempUnit: TextView = listItemView.findViewById(R.id.db_minor_temp)
fun bindData(weather: WeatherDisplay?){ fun bindData(weather: WeatherDisplay?) {
locationTV.text = weather?.location locationTV.text = weather?.location
conditionTV.text = weather?.description conditionTV.text = weather?.description
weatherIV.loadImage(weather?.iconURL) weatherIV.loadImage(weather?.iconURL)
@@ -90,7 +92,6 @@ class WorldRecyclerAdapter(
} }
internal class EmptyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
internal class EmptyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
} }

View File

@@ -2,9 +2,9 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<gradient <gradient
android:startColor="@color/colour_two" android:angle="45"
android:centerColor="@color/colour_three" android:centerColor="@color/colour_three"
android:endColor="@color/colour_four" android:endColor="@color/colour_four"
android:type="linear" android:startColor="@color/colour_two"
android:angle="45"/> android:type="linear" />
</shape> </shape>

View File

@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:tint="#FFFFFF"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="2.61"
android:scaleY="2.61"
android:translateX="22.68"
android:translateY="22.68">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z" />
</group>
</vector>

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_margin="24dp"
android:orientation="vertical">
<EditText
android:id="@+id/location_name_tv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:ems="10"
android:hint="@string/location_name"
android:inputType="textPersonName"
android:maxLines="2"
tools:text="Greater London" />
<Button
android:id="@+id/submit"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="@string/submit"
android:textColor="#ffffff"
android:textStyle="bold" />
</LinearLayout>
<FrameLayout
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:visibility="gone">
<ProgressBar
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
</RelativeLayout>

View File

@@ -3,11 +3,13 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -20,13 +22,15 @@
android:layout_weight="2"> android:layout_weight="2">
<ImageView <ImageView
android:src="@drawable/somethingnew" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:src="@drawable/somethingnew" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="2"> android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -55,6 +59,7 @@
android:layout_weight="3" android:layout_weight="3"
tools:text="11" /> tools:text="11" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -72,6 +77,7 @@
android:layout_weight="3" android:layout_weight="3"
tools:text="11" /> tools:text="11" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -96,6 +102,7 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -107,13 +114,14 @@
android:layout_weight="2"> android:layout_weight="2">
<ImageView <ImageView
android:src="@drawable/breeze" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:src="@drawable/breeze" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_weight="2"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -137,12 +145,12 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="7mph" android:text="7mph" />
/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -154,13 +162,15 @@
android:layout_weight="2"> android:layout_weight="2">
<ImageView <ImageView
android:src="@drawable/water_drop" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:src="@drawable/water_drop" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_weight="2"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -187,9 +197,9 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="85%" android:text="85%" />
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -205,8 +215,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="11mm" android:text="11mm" />
/>
</LinearLayout> </LinearLayout>
@@ -215,6 +224,7 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -226,13 +236,15 @@
android:layout_weight="2"> android:layout_weight="2">
<ImageView <ImageView
android:src="@drawable/sunrise" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:src="@drawable/sunrise" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_weight="2"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -259,8 +271,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="7" android:text="7" />
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@@ -278,9 +289,9 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="05:30am" android:text="05:30am" />
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -296,8 +307,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="06:12pm" android:text="06:12pm" />
/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content" android:id="@+id/main_content"
@@ -17,19 +16,19 @@
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:popupTheme="@style/AppTheme.PopupOverlay" app:popupTheme="@style/AppTheme.PopupOverlay"
tools:title="Atlas Weather"/> tools:title="Atlas Weather" />
<com.google.android.material.bottomnavigation.BottomNavigationView <com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view" android:id="@+id/nav_view"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="60dp" android:layout_height="60dp"
app:backgroundTint="@android:color/transparent"
app:elevation="0dp"
app:itemIconTint="@android:color/background_light" app:itemIconTint="@android:color/background_light"
app:itemTextColor="@android:color/background_light" app:itemTextColor="@android:color/background_light"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:backgroundTint="@android:color/transparent"
app:elevation="0dp"
app:menu="@menu/tabs_menu" /> app:menu="@menu/tabs_menu" />
<fragment <fragment
@@ -42,7 +41,7 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" app:layout_constraintTop_toBottomOf="@id/toolbar"
tools:layout="@layout/fragment_home"/> tools:layout="@layout/fragment_home" />
<ProgressBar <ProgressBar
android:id="@+id/progress_circular" android:id="@+id/progress_circular"

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -8,39 +7,39 @@
tools:context="com.appttude.h_mal.atlas_weather.ui.world.AddLocationFragment"> tools:context="com.appttude.h_mal.atlas_weather.ui.world.AddLocationFragment">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/world_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent" android:divider="@null"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
android:id="@+id/world_recycler" app:layout_constraintTop_toTopOf="parent" />
android:divider="@null">
</androidx.recyclerview.widget.RecyclerView>
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingActionButton" android:id="@+id/floatingActionButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginBottom="36dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="24dp"
android:layout_marginBottom="36dp"
android:clickable="true" android:clickable="true"
app:srcCompat="@android:drawable/ic_input_add" android:contentDescription="@string/image_string"
android:focusable="true"
android:tint="@android:color/white" android:tint="@android:color/white"
app:elevation="0dp" app:elevation="0dp"
android:focusable="true" /> app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:srcCompat="@android:drawable/ic_input_add" />
<ProgressBar <ProgressBar
android:id="@+id/progressBar2" android:id="@+id/progressBar2"
style="?android:attr/progressBarStyle" style="?android:attr/progressBarStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent"
android:visibility="gone" tools:visibility="visible" />
tools:visibility="visible"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -20,8 +20,8 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginRight="6dp" android:layout_marginRight="6dp"
android:tint="@color/colorAccent" android:src="@drawable/location_flag"
android:src="@drawable/location_flag" /> android:tint="@color/colorAccent" />
<TextView <TextView
android:id="@+id/location_main_4" android:id="@+id/location_main_4"
@@ -58,9 +58,9 @@
android:textSize="30sp" /> android:textSize="30sp" />
<LinearLayout <LinearLayout
android:layout_below="@id/location_holder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/location_holder"
android:orientation="horizontal"> android:orientation="horizontal">
<View <View
@@ -84,8 +84,7 @@
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginRight="15dp" android:layout_marginRight="15dp"
android:layout_weight="6" android:layout_weight="6"
android:orientation="vertical" android:orientation="vertical">
>
<TextView <TextView
android:id="@+id/condition_main_4" android:id="@+id/condition_main_4"

View File

@@ -7,12 +7,12 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:cardElevation="0dp" android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:backgroundTint="@android:color/transparent" android:backgroundTint="@android:color/transparent"
app:cardElevation="0dp"
card_view:cardPreventCornerOverlap="false" card_view:cardPreventCornerOverlap="false"
card_view:cardUseCompatPadding="true"> card_view:cardUseCompatPadding="true">

View File

@@ -15,8 +15,8 @@
android:layout_weight="2"> android:layout_weight="2">
<ImageView <ImageView
android:src="@drawable/breeze" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:src="@drawable/breeze" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
@@ -50,8 +50,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="11kmp" android:text="11kmp" />
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@@ -70,8 +69,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="SW" android:text="SW" />
/>
</LinearLayout> </LinearLayout>
@@ -92,7 +90,7 @@
android:layout_weight="2"> android:layout_weight="2">
<ImageView <ImageView
style="@style/icon_style__further_deatils" style="@style/icon_style__further_details"
android:src="@drawable/water_drop" /> android:src="@drawable/water_drop" />
</FrameLayout> </FrameLayout>
@@ -126,8 +124,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="85%" android:text="85%" />
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@@ -145,8 +142,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="11mm" android:text="11mm" />
/>
</LinearLayout> </LinearLayout>
@@ -167,7 +163,7 @@
android:layout_weight="2"> android:layout_weight="2">
<ImageView <ImageView
style="@style/icon_style__further_deatils" style="@style/icon_style__further_details"
android:src="@drawable/cloud_symbol" /> android:src="@drawable/cloud_symbol" />
</FrameLayout> </FrameLayout>
@@ -202,8 +198,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="85%" android:text="85%" />
/>
</LinearLayout> </LinearLayout>

View File

@@ -76,11 +76,11 @@
<TextView <TextView
android:id="@+id/widget_current_location" android:id="@+id/widget_current_location"
style="@style/widget_light_home_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:maxWidth="180dp" android:maxWidth="180dp"
android:maxLines="1" android:maxLines="1"
style="@style/widget_light_home_text"
tools:text="Hammersmith Bridge" /> tools:text="Hammersmith Bridge" />
</LinearLayout> </LinearLayout>

View File

Before

Width:  |  Height:  |  Size: 671 B

After

Width:  |  Height:  |  Size: 671 B

View File

Before

Width:  |  Height:  |  Size: 881 B

After

Width:  |  Height:  |  Size: 881 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -32,7 +32,7 @@
tools:layout="@layout/fragment__two"> tools:layout="@layout/fragment__two">
<action <action
android:id="@+id/action_worldFragment_to_addLocationFragment" android:id="@+id/action_worldFragment_to_addLocationFragment"
app:destination="@id/addLocationFragment"/> app:destination="@id/addLocationFragment" />
<action <action
android:id="@+id/action_worldFragment_to_worldItemFragment" android:id="@+id/action_worldFragment_to_worldItemFragment"
app:destination="@id/worldItemFragment" /> app:destination="@id/worldItemFragment" />

View File

@@ -1,4 +1,7 @@
<resources> <resources>
<!-- TODO: Remove or change this placeholder text --> <string name="min">Min:</string>
<string name="hello_blank_fragment">Hello blank fragment</string> <string name="max">Max:</string>
<string name="average">Average:</string>
<string name="floating_action_button">Floating Action Button</string>
<string name="_11mm">11mm</string>
</resources> </resources>

View File

@@ -3,13 +3,13 @@
android:configure="com.appttude.h_mal.atlas_weather.ui.widget.WidgetLocationPermissionActivity" android:configure="com.appttude.h_mal.atlas_weather.ui.widget.WidgetLocationPermissionActivity"
android:initialKeyguardLayout="@layout/weather_app_widget" android:initialKeyguardLayout="@layout/weather_app_widget"
android:initialLayout="@layout/weather_app_widget" android:initialLayout="@layout/weather_app_widget"
android:minHeight="110.0dp"
android:minWidth="320.0dp" android:minWidth="320.0dp"
android:minHeight="110.0dp"
android:minResizeWidth="320.0dp" android:minResizeWidth="320.0dp"
android:minResizeHeight="110.0dp" android:minResizeHeight="110.0dp"
android:previewImage="@drawable/widget_screenshot" android:previewImage="@drawable/widget_screenshot"
android:updatePeriodMillis="1800000"
android:resizeMode="vertical" android:resizeMode="vertical"
android:updatePeriodMillis="1800000"
android:widgetCategory="home_screen"> android:widgetCategory="home_screen">
</appwidget-provider> </appwidget-provider>

View File

@@ -1,32 +1,32 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <PreferenceCategory android:title="Units">--> <!-- <PreferenceCategory android:title="Units">-->
<!-- <ListPreference--> <!-- <ListPreference-->
<!-- android:defaultValue="°C"--> <!-- android:defaultValue="°C"-->
<!-- android:entries="@array/list_preference_temp"--> <!-- android:entries="@array/list_preference_temp"-->
<!-- android:entryValues="@array/list_preference_temp"--> <!-- android:entryValues="@array/list_preference_temp"-->
<!-- android:key="temp_units"--> <!-- android:key="temp_units"-->
<!-- android:title="Temperature Units" />--> <!-- android:title="Temperature Units" />-->
<!-- <ListPreference--> <!-- <ListPreference-->
<!-- android:defaultValue="kph"--> <!-- android:defaultValue="kph"-->
<!-- android:entries="@array/list_preference_wind"--> <!-- android:entries="@array/list_preference_wind"-->
<!-- android:entryValues="@array/list_preference_wind_values"--> <!-- android:entryValues="@array/list_preference_wind_values"-->
<!-- android:key="wind_units"--> <!-- android:key="wind_units"-->
<!-- android:title="Wind Units" />--> <!-- android:title="Wind Units" />-->
<!-- <ListPreference--> <!-- <ListPreference-->
<!-- android:defaultValue="mm"--> <!-- android:defaultValue="mm"-->
<!-- android:entries="@array/list_preference_precip"--> <!-- android:entries="@array/list_preference_precip"-->
<!-- android:entryValues="@array/list_preference_precip_values"--> <!-- android:entryValues="@array/list_preference_precip_values"-->
<!-- android:key="precip_units"--> <!-- android:key="precip_units"-->
<!-- android:title="Precipitation Units" />--> <!-- android:title="Precipitation Units" />-->
<!-- <ListPreference--> <!-- <ListPreference-->
<!-- android:defaultValue="km"--> <!-- android:defaultValue="km"-->
<!-- android:entries="@array/list_preference_vis"--> <!-- android:entries="@array/list_preference_vis"-->
<!-- android:entryValues="@array/list_preference_vis_values"--> <!-- android:entryValues="@array/list_preference_vis_values"-->
<!-- android:key="vis_units"--> <!-- android:key="vis_units"-->
<!-- android:title="Visibility Units" />--> <!-- android:title="Visibility Units" />-->
<!-- </PreferenceCategory>--> <!-- </PreferenceCategory>-->
<PreferenceCategory android:title="Notification Settings"> <PreferenceCategory android:title="Notification Settings">
<SwitchPreference <SwitchPreference
android:defaultValue="true" android:defaultValue="true"

View File

@@ -10,8 +10,6 @@
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<application android:networkSecurityConfig="@xml/network_security_config" />
<uses-feature <uses-feature
android:name="android.hardware.location" android:name="android.hardware.location"
android:required="true" /> android:required="true" />
@@ -19,4 +17,8 @@
android:name="android.hardware.location.gps" android:name="android.hardware.location.gps"
android:required="true" /> android:required="true" />
<application
android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="MissingApplicationIcon" />
</manifest> </manifest>

View File

@@ -9,12 +9,11 @@ import android.location.LocationManager
import android.os.HandlerThread import android.os.HandlerThread
import androidx.annotation.RequiresPermission import androidx.annotation.RequiresPermission
import com.appttude.h_mal.atlas_weather.model.types.LocationType import com.appttude.h_mal.atlas_weather.model.types.LocationType
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationRequest.PRIORITY_HIGH_ACCURACY
import com.google.android.gms.location.LocationRequest.PRIORITY_LOW_POWER
import com.google.android.gms.location.LocationResult import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.google.android.gms.tasks.CancellationToken import com.google.android.gms.tasks.CancellationToken
import com.google.android.gms.tasks.OnTokenCanceledListener import com.google.android.gms.tasks.OnTokenCanceledListener
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.tasks.await
@@ -29,7 +28,7 @@ class LocationProviderImpl(
) : LocationProvider, LocationHelper(applicationContext) { ) : LocationProvider, LocationHelper(applicationContext) {
private var locationManager = private var locationManager =
applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager? applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager?
private val client = FusedLocationProviderClient(applicationContext) private val client = LocationServices.getFusedLocationProviderClient(applicationContext)
private val geoCoder: Geocoder by lazy { Geocoder(applicationContext, Locale.getDefault()) } private val geoCoder: Geocoder by lazy { Geocoder(applicationContext, Locale.getDefault()) }
@RequiresPermission(value = ACCESS_COARSE_LOCATION) @RequiresPermission(value = ACCESS_COARSE_LOCATION)
@@ -60,6 +59,7 @@ class LocationProviderImpl(
?: address.municipality ?: address.municipality
location ?: throw IOException("No location municipalitySubdivision or municipality") location ?: throw IOException("No location municipalitySubdivision or municipality")
} }
LocationType.City -> { LocationType.City -> {
address.municipality ?: throw IOException("No location municipality") address.municipality ?: throw IOException("No location municipality")
} }
@@ -68,7 +68,7 @@ class LocationProviderImpl(
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
private suspend fun getAFreshLocation(): Location? { private suspend fun getAFreshLocation(): Location? {
return client.getCurrentLocation(PRIORITY_LOW_POWER, object : CancellationToken() { return client.getCurrentLocation(Priority.PRIORITY_LOW_POWER, object : CancellationToken() {
override fun isCancellationRequested(): Boolean = false override fun isCancellationRequested(): Boolean = false
override fun onCanceledRequested(p0: OnTokenCanceledListener): CancellationToken = this override fun onCanceledRequested(p0: OnTokenCanceledListener): CancellationToken = this
}).await() }).await()
@@ -84,20 +84,30 @@ class LocationProviderImpl(
return suspendCoroutine { cont -> return suspendCoroutine { cont ->
val callback = object : LocationCallback() { val callback = object : LocationCallback() {
override fun onLocationResult(p0: LocationResult?) { override fun onLocationResult(p0: LocationResult) {
client.removeLocationUpdates(this) client.removeLocationUpdates(this)
cont.resume(p0?.lastLocation) cont.resume(p0.lastLocation)
} }
} }
with(locationManager!!) { with(locationManager!!) {
when { when {
isProviderEnabled(LocationManager.GPS_PROVIDER) -> { isProviderEnabled(LocationManager.GPS_PROVIDER) -> {
client.requestLocationUpdates(createLocationRequest(PRIORITY_HIGH_ACCURACY), callback, looper) client.requestLocationUpdates(
createLocationRequest(Priority.PRIORITY_HIGH_ACCURACY),
callback,
looper
)
} }
isProviderEnabled(LocationManager.NETWORK_PROVIDER) -> { isProviderEnabled(LocationManager.NETWORK_PROVIDER) -> {
client.requestLocationUpdates(createLocationRequest(PRIORITY_LOW_POWER), callback, looper) client.requestLocationUpdates(
createLocationRequest(Priority.PRIORITY_LOW_POWER),
callback,
looper
)
} }
else -> { else -> {
cont.resume(null) cont.resume(null)
} }

View File

@@ -8,7 +8,7 @@ open class BaseNetworkModule {
// Declare the method we want/can change (no annotations) // Declare the method we want/can change (no annotations)
open fun baseUrl() = "/" open fun baseUrl() = "/"
inline fun <reified T: Api> invoke( inline fun <reified T : Api> invoke(
vararg interceptors: Interceptor vararg interceptors: Interceptor
): Api { ): Api {

View File

@@ -7,7 +7,6 @@ import java.io.IOException
abstract class ResponseUnwrap { abstract class ResponseUnwrap {
@Suppress("BlockingMethodInNonBlockingContext")
suspend fun <T : Any> responseUnwrap( suspend fun <T : Any> responseUnwrap(
call: suspend () -> Response<T> call: suspend () -> Response<T>
): T { ): T {

View File

@@ -6,7 +6,7 @@ import retrofit2.http.GET
import retrofit2.http.Query import retrofit2.http.Query
interface WeatherApi: Api { interface WeatherApi : Api {
@GET("onecall?") @GET("onecall?")
suspend fun getFromApi( suspend fun getFromApi(

View File

@@ -12,7 +12,7 @@ class NetworkConnectionInterceptor(
private val applicationContext = context.applicationContext private val applicationContext = context.applicationContext
override fun intercept(chain: Interceptor.Chain): okhttp3.Response { override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
if (!isInternetAvailable(applicationContext)){ if (!isInternetAvailable(applicationContext)) {
throw IOException("Make sure you have an active data connection") throw IOException("Make sure you have an active data connection")
} }
return chain.proceed(chain.request()) return chain.proceed(chain.request())

View File

@@ -8,7 +8,7 @@ import okhttp3.Response
/** /**
* Interceptor used to add default query parameters to api calls * Interceptor used to add default query parameters to api calls
*/ */
class QueryParamsInterceptor : Interceptor{ class QueryParamsInterceptor : Interceptor {
val id = BuildConfig.ParamOne val id = BuildConfig.ParamOne

View File

@@ -10,7 +10,7 @@ import java.util.concurrent.TimeUnit
val loggingInterceptor = HttpLoggingInterceptor().apply { val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY level = HttpLoggingInterceptor.Level.BODY
} }
fun buildOkHttpClient( fun buildOkHttpClient(
vararg interceptor: Interceptor, vararg interceptor: Interceptor,

View File

@@ -9,9 +9,10 @@ import com.appttude.h_mal.atlas_weather.data.room.entity.CURRENT_LOCATION
* Shared preferences to save & load last timestamp * Shared preferences to save & load last timestamp
*/ */
const val LOCATION_CONST = "location_" const val LOCATION_CONST = "location_"
class PreferenceProvider( class PreferenceProvider(
context: Context context: Context
){ ) {
private val appContext = context.applicationContext private val appContext = context.applicationContext
@@ -25,7 +26,7 @@ class PreferenceProvider(
).apply() ).apply()
} }
fun getLastSavedAt(locationName: String): Long? { fun getLastSavedAt(locationName: String): Long {
return preference.getLong(locationName, 0L) return preference.getLong(locationName, 0L)
} }
@@ -33,17 +34,17 @@ class PreferenceProvider(
remove(CURRENT_LOCATION) remove(CURRENT_LOCATION)
} }
fun deleteLocation(locationName: String){ fun deleteLocation(locationName: String) {
preference.edit().remove(locationName).apply() preference.edit().remove(locationName).apply()
} }
fun isNotificationsEnabled(): Boolean = preference.getBoolean("notif_boolean", true) fun isNotificationsEnabled(): Boolean = preference.getBoolean("notif_boolean", true)
fun setFirstTimeRun(){ fun setFirstTimeRun() {
preference.edit().putBoolean("FIRST_TIME_RUN", false).apply() preference.edit().putBoolean("FIRST_TIME_RUN", false).apply()
} }
fun isWidgetBlackground(): Boolean { fun isWidgetBackground(): Boolean {
return preference.getBoolean("widget_black_background", false) return preference.getBoolean("widget_black_background", false)
} }

View File

@@ -10,7 +10,7 @@ interface Repository {
suspend fun saveCurrentWeatherToRoom(entityItem: EntityItem) suspend fun saveCurrentWeatherToRoom(entityItem: EntityItem)
suspend fun saveWeatherListToRoom(list: List<EntityItem>) suspend fun saveWeatherListToRoom(list: List<EntityItem>)
fun loadRoomWeatherLiveData(): LiveData<List<EntityItem>> fun loadRoomWeatherLiveData(): LiveData<List<EntityItem>>
suspend fun loadWeatherList() : List<String> suspend fun loadWeatherList(): List<String>
fun loadCurrentWeatherFromRoom(id: String): LiveData<EntityItem> fun loadCurrentWeatherFromRoom(id: String): LiveData<EntityItem>
suspend fun loadSingleCurrentWeatherFromRoom(id: String): EntityItem suspend fun loadSingleCurrentWeatherFromRoom(id: String): EntityItem
fun isSearchValid(locationName: String): Boolean fun isSearchValid(locationName: String): Boolean

View File

@@ -23,29 +23,29 @@ class RepositoryImpl(
return responseUnwrap { api.getFromApi(lat, long) } return responseUnwrap { api.getFromApi(lat, long) }
} }
override suspend fun saveCurrentWeatherToRoom(entityItem: EntityItem){ override suspend fun saveCurrentWeatherToRoom(entityItem: EntityItem) {
db.getSimpleDao().upsertFullWeather(entityItem) db.getSimpleDao().upsertFullWeather(entityItem)
} }
override suspend fun saveWeatherListToRoom( override suspend fun saveWeatherListToRoom(
list: List<EntityItem> list: List<EntityItem>
){ ) {
db.getSimpleDao().upsertListOfFullWeather(list) db.getSimpleDao().upsertListOfFullWeather(list)
} }
override fun loadRoomWeatherLiveData() = db.getSimpleDao().getAllFullWeatherWithoutCurrent() override fun loadRoomWeatherLiveData() = db.getSimpleDao().getAllFullWeatherWithoutCurrent()
override suspend fun loadWeatherList() : List<String>{ override suspend fun loadWeatherList(): List<String> {
return db.getSimpleDao() return db.getSimpleDao()
.getWeatherListWithoutCurrent() .getWeatherListWithoutCurrent()
.map { it.id } .map { it.id }
} }
override fun loadCurrentWeatherFromRoom(id: String) override fun loadCurrentWeatherFromRoom(id: String) =
= db.getSimpleDao().getCurrentFullWeather(id) db.getSimpleDao().getCurrentFullWeather(id)
override suspend fun loadSingleCurrentWeatherFromRoom(id: String) override suspend fun loadSingleCurrentWeatherFromRoom(id: String) =
= db.getSimpleDao().getCurrentFullWeatherSingle(id) db.getSimpleDao().getCurrentFullWeatherSingle(id)
override fun isSearchValid(locationName: String): Boolean { override fun isSearchValid(locationName: String): Boolean {
val lastSaved = prefs val lastSaved = prefs

View File

@@ -4,11 +4,11 @@ import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider
class SettingsRepositoryImpl( class SettingsRepositoryImpl(
private val prefs: PreferenceProvider private val prefs: PreferenceProvider
) : SettingsRepository{ ) : SettingsRepository {
override fun isNotificationsEnabled(): Boolean = prefs.isNotificationsEnabled() override fun isNotificationsEnabled(): Boolean = prefs.isNotificationsEnabled()
override fun setFirstTime() = prefs.setFirstTimeRun() override fun setFirstTime() = prefs.setFirstTimeRun()
override fun isBlackBackground() = prefs.isWidgetBlackground() override fun isBlackBackground() = prefs.isWidgetBackground()
} }

View File

@@ -18,16 +18,16 @@ interface WeatherDao {
fun upsertListOfFullWeather(items: List<EntityItem>) fun upsertListOfFullWeather(items: List<EntityItem>)
@Query("SELECT * FROM EntityItem WHERE id = :userId LIMIT 1") @Query("SELECT * FROM EntityItem WHERE id = :userId LIMIT 1")
fun getCurrentFullWeather(userId: String) : LiveData<EntityItem> fun getCurrentFullWeather(userId: String): LiveData<EntityItem>
@Query("SELECT * FROM EntityItem WHERE id = :userId LIMIT 1") @Query("SELECT * FROM EntityItem WHERE id = :userId LIMIT 1")
fun getCurrentFullWeatherSingle(userId: String) : EntityItem fun getCurrentFullWeatherSingle(userId: String): EntityItem
@Query("SELECT * FROM EntityItem WHERE id != :id") @Query("SELECT * FROM EntityItem WHERE id != :id")
fun getAllFullWeatherWithoutCurrent(id: String = CURRENT_LOCATION) : LiveData<List<EntityItem>> fun getAllFullWeatherWithoutCurrent(id: String = CURRENT_LOCATION): LiveData<List<EntityItem>>
@Query("SELECT * FROM EntityItem WHERE id != :id") @Query("SELECT * FROM EntityItem WHERE id != :id")
fun getWeatherListWithoutCurrent(id: String = CURRENT_LOCATION) : List<EntityItem> fun getWeatherListWithoutCurrent(id: String = CURRENT_LOCATION): List<EntityItem>
@Query("DELETE FROM EntityItem WHERE id = :userId") @Query("DELETE FROM EntityItem WHERE id = :userId")
fun deleteEntry(userId: String): Int fun deleteEntry(userId: String): Int

View File

@@ -6,6 +6,7 @@ import com.appttude.h_mal.atlas_weather.model.weather.FullWeather
const val CURRENT_LOCATION = "CurrentLocation" const val CURRENT_LOCATION = "CurrentLocation"
@Entity @Entity
data class EntityItem( data class EntityItem(
@PrimaryKey(autoGenerate = false) @PrimaryKey(autoGenerate = false)

View File

@@ -1,7 +1,5 @@
package com.appttude.h_mal.atlas_weather.helper package com.appttude.h_mal.atlas_weather.helper
import android.view.LayoutInflater
import android.view.ViewGroup
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType
import kotlin.reflect.KClass import kotlin.reflect.KClass

View File

@@ -41,7 +41,8 @@ class ServicesHelper(
// Get weather from api // Get weather from api
val weather = repository val weather = repository
.getWeatherFromApi(latLong.first.toString(), latLong.second.toString()) .getWeatherFromApi(latLong.first.toString(), latLong.second.toString())
val currentLocation = locationProvider.getLocationNameFromLatLong(weather.lat, weather.lon) val currentLocation =
locationProvider.getLocationNameFromLatLong(weather.lat, weather.lon)
val fullWeather = FullWeather(weather).apply { val fullWeather = FullWeather(weather).apply {
temperatureUnit = "°C" temperatureUnit = "°C"
locationString = currentLocation locationString = currentLocation

View File

@@ -23,7 +23,7 @@ data class Forecast(
val sunrise: String?, val sunrise: String?,
val sunset: String?, val sunset: String?,
val cloud: String? val cloud: String?
): Parcelable{ ) : Parcelable {
constructor(parcel: Parcel) : this( constructor(parcel: Parcel) : this(
parcel.readString(), parcel.readString(),

View File

@@ -22,7 +22,7 @@ data class WeatherDisplay(
val lat: Double = 0.00, val lat: Double = 0.00,
val lon: Double = 0.00, val lon: Double = 0.00,
var displayName: String? var displayName: String?
): Parcelable { ) : Parcelable {
constructor(parcel: Parcel) : this( constructor(parcel: Parcel) : this(
parcel.readValue(Double::class.java.classLoader) as? Double, parcel.readValue(Double::class.java.classLoader) as? Double,

View File

@@ -1,6 +1,6 @@
package com.appttude.h_mal.atlas_weather.model.types package com.appttude.h_mal.atlas_weather.model.types
enum class LocationType{ enum class LocationType {
City, City,
Town Town
} }

View File

@@ -25,9 +25,9 @@ data class DailyWeather(
val pop: Double?, val pop: Double?,
val uvi: Double?, val uvi: Double?,
val rain: Double? val rain: Double?
){ ) {
constructor(dailyItem: DailyItem): this( constructor(dailyItem: DailyItem) : this(
dailyItem.dt, dailyItem.dt,
dailyItem.sunrise, dailyItem.sunrise,
dailyItem.sunset, dailyItem.sunset,

View File

@@ -14,11 +14,11 @@ data class FullWeather(
var temperatureUnit: String? = null var temperatureUnit: String? = null
) { ) {
constructor(weatherResponse: WeatherResponse): this( constructor(weatherResponse: WeatherResponse) : this(
weatherResponse.current?.let { Current(it) }, weatherResponse.current?.let { Current(it) },
weatherResponse.timezone, weatherResponse.timezone,
weatherResponse.timezoneOffset, weatherResponse.timezoneOffset,
weatherResponse.hourly?.subList(0,23)?.map { Hour(it) }, weatherResponse.hourly?.subList(0, 23)?.map { Hour(it) },
weatherResponse.daily?.map { DailyWeather(it) }, weatherResponse.daily?.map { DailyWeather(it) },
weatherResponse.lon, weatherResponse.lon,
weatherResponse.lat weatherResponse.lat

View File

@@ -10,7 +10,7 @@ data class Hour(
val dt: Int? = null, val dt: Int? = null,
val temp: Double? = null, val temp: Double? = null,
val icon: String? = null val icon: String? = null
): Parcelable { ) : Parcelable {
constructor(parcel: Parcel) : this( constructor(parcel: Parcel) : this(
parcel.readValue(Int::class.java.classLoader) as? Int, parcel.readValue(Int::class.java.classLoader) as? Int,

View File

@@ -14,11 +14,11 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.appttude.h_mal.atlas_weather.application.LOCATION_PERMISSION_REQUEST import com.appttude.h_mal.atlas_weather.application.LOCATION_PERMISSION_REQUEST
import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory
import com.appttude.h_mal.atlas_weather.utils.Event 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.displayToast
import com.appttude.h_mal.atlas_weather.utils.hide import com.appttude.h_mal.atlas_weather.utils.hide
import com.appttude.h_mal.atlas_weather.utils.show import com.appttude.h_mal.atlas_weather.utils.show
import com.appttude.h_mal.atlas_weather.viewmodel.ApplicationViewModelFactory
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -27,6 +27,7 @@ import org.kodein.di.android.x.kodein
import org.kodein.di.generic.instance import org.kodein.di.generic.instance
import kotlin.properties.Delegates import kotlin.properties.Delegates
@Suppress("EmptyMethod", "EmptyMethod")
abstract class BaseFragment(@LayoutRes contentLayoutId: Int) : Fragment(contentLayoutId), abstract class BaseFragment(@LayoutRes contentLayoutId: Int) : Fragment(contentLayoutId),
KodeinAware { KodeinAware {

View File

@@ -1,8 +1,6 @@
package com.appttude.h_mal.atlas_weather.ui package com.appttude.h_mal.atlas_weather.ui
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController import androidx.navigation.NavController
@@ -12,7 +10,7 @@ import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.appttude.h_mal.atlas_weather.R import com.appttude.h_mal.atlas_weather.R
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import kotlinx.android.synthetic.main.activity_main_navigation.* import kotlinx.android.synthetic.main.activity_main_navigation.toolbar
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {

View File

@@ -6,7 +6,8 @@ import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
inline fun <reified T> parcelableCreator( inline fun <reified T> parcelableCreator(
crossinline create: (Parcel) -> T) = crossinline create: (Parcel) -> T
) =
object : Parcelable.Creator<T> { object : Parcelable.Creator<T> {
override fun createFromParcel(source: Parcel) = create(source) override fun createFromParcel(source: Parcel) = create(source)
override fun newArray(size: Int) = arrayOfNulls<T>(size) override fun newArray(size: Int) = arrayOfNulls<T>(size)
@@ -18,7 +19,7 @@ suspend fun <T : Any?> tryOrNullSuspended(
return try { return try {
call.invoke() call.invoke()
}catch (e: Exception){ } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
null null
} }
@@ -30,7 +31,7 @@ fun <T : Any?> tryOrNull(
return try { return try {
call.invoke() call.invoke()
}catch (e: Exception){ } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
null null
} }
@@ -46,9 +47,9 @@ fun <T : Any?> tryOrNull(
* *
* Both equal 2. * Both equal 2.
*/ */
suspend fun <T: Any> createSuspend( suspend fun <T : Any> createSuspend(
call: () -> T? call: () -> T?
): T?{ ): T? {
return suspendCoroutine { cont -> return suspendCoroutine { cont ->
cont.resume(call()) cont.resume(call())

View File

@@ -6,7 +6,7 @@ import androidx.navigation.NavDirections
import androidx.navigation.Navigation import androidx.navigation.Navigation
import com.appttude.h_mal.atlas_weather.R import com.appttude.h_mal.atlas_weather.R
fun Fragment.navigateToFragment(newFragment: Fragment){ fun Fragment.navigateToFragment(newFragment: Fragment) {
childFragmentManager.beginTransaction() childFragmentManager.beginTransaction()
.add(R.id.container, newFragment) .add(R.id.container, newFragment)
.commit() .commit()

View File

@@ -4,9 +4,7 @@ import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.NetworkCapabilities import android.net.NetworkCapabilities
fun isInternetAvailable( fun isInternetAvailable(context: Context): Boolean {
context: Context
): Boolean {
var result = false var result = false
val connectivityManager = val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?

View File

@@ -1,13 +1,13 @@
package com.appttude.h_mal.atlas_weather.utils package com.appttude.h_mal.atlas_weather.utils
import android.os.Build
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.time.Instant import java.time.Instant
import java.time.OffsetTime import java.time.OffsetTime
import java.time.ZoneOffset import java.time.ZoneOffset
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.* import java.util.Date
import java.util.Locale
fun Int.toDayString(): String { fun Int.toDayString(): String {
return try { return try {
@@ -46,13 +46,8 @@ fun Int.toSmallDayName(): String {
fun Int?.toTime(): String? { fun Int?.toTime(): String? {
return this?.makeMilliseconds()?.let { return this?.makeMilliseconds()?.let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { OffsetTime.ofInstant(Instant.ofEpochMilli(it), ZoneOffset.UTC)
OffsetTime.ofInstant(Instant.ofEpochMilli(it), ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("HH:mm")) .format(DateTimeFormatter.ofPattern("HH:mm"))
} else {
val date = Date(it)
val format = SimpleDateFormat("HH:mm", Locale.getDefault())
format.format(date)
}
} }
} }

View File

@@ -1,7 +1,7 @@
package com.appttude.h_mal.atlas_weather.utils package com.appttude.h_mal.atlas_weather.utils
fun generateIconUrlString(icon: String?): String?{ fun generateIconUrlString(icon: String?): String? {
return icon?.let { return icon?.let {
StringBuilder() StringBuilder()
.append("http://openweathermap.org/img/wn/") .append("http://openweathermap.org/img/wn/")

View File

@@ -2,7 +2,6 @@ package com.appttude.h_mal.atlas_weather.utils
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -33,7 +32,7 @@ fun ViewGroup.generateView(layoutId: Int): View = LayoutInflater
.from(context) .from(context)
.inflate(layoutId, this, false) .inflate(layoutId, this, false)
fun ImageView.loadImage(url: String?){ fun ImageView.loadImage(url: String?) {
Picasso.get().load(url) Picasso.get().load(url)
.placeholder(R.drawable.ic_baseline_cloud_queue_24) .placeholder(R.drawable.ic_baseline_cloud_queue_24)
.error(R.drawable.ic_baseline_cloud_off_24) .error(R.drawable.ic_baseline_cloud_off_24)

View File

@@ -13,10 +13,18 @@ class ApplicationViewModelFactory(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
with(modelClass){ with(modelClass) {
return when{ return when {
isAssignableFrom(WorldViewModel::class.java) -> WorldViewModel(locationProvider, repository) isAssignableFrom(WorldViewModel::class.java) -> WorldViewModel(
isAssignableFrom(MainViewModel::class.java) -> MainViewModel(locationProvider, repository) locationProvider,
repository
)
isAssignableFrom(MainViewModel::class.java) -> MainViewModel(
locationProvider,
repository
)
else -> throw IllegalArgumentException("Unknown ViewModel class") else -> throw IllegalArgumentException("Unknown ViewModel class")
} as T } as T
} }

View File

@@ -17,7 +17,7 @@ import kotlinx.coroutines.launch
class MainViewModel( class MainViewModel(
private val locationProvider: LocationProvider, private val locationProvider: LocationProvider,
private val repository: Repository private val repository: Repository
): WeatherViewModel(){ ) : WeatherViewModel() {
val weatherLiveData = MutableLiveData<WeatherDisplay>() val weatherLiveData = MutableLiveData<WeatherDisplay>()
@@ -35,8 +35,8 @@ class MainViewModel(
} }
@RequiresPermission(value = Manifest.permission.ACCESS_COARSE_LOCATION) @RequiresPermission(value = Manifest.permission.ACCESS_COARSE_LOCATION)
fun fetchData(){ fun fetchData() {
if (!repository.isSearchValid(CURRENT_LOCATION)){ if (!repository.isSearchValid(CURRENT_LOCATION)) {
operationRefresh.postValue(Event(false)) operationRefresh.postValue(Event(false))
return return
} }
@@ -49,15 +49,16 @@ class MainViewModel(
// Get weather from api // Get weather from api
val weather = repository val weather = repository
.getWeatherFromApi(latLong.first.toString(), latLong.second.toString()) .getWeatherFromApi(latLong.first.toString(), latLong.second.toString())
val currentLocation = locationProvider.getLocationNameFromLatLong(weather.lat, weather.lon) val currentLocation =
locationProvider.getLocationNameFromLatLong(weather.lat, weather.lon)
val fullWeather = createFullWeather(weather, currentLocation) val fullWeather = createFullWeather(weather, currentLocation)
val entityItem = EntityItem(CURRENT_LOCATION, fullWeather) val entityItem = EntityItem(CURRENT_LOCATION, fullWeather)
// Save data if not null // Save data if not null
repository.saveLastSavedAt(CURRENT_LOCATION) repository.saveLastSavedAt(CURRENT_LOCATION)
repository.saveCurrentWeatherToRoom(entityItem) repository.saveCurrentWeatherToRoom(entityItem)
}catch (e: Exception){ } catch (e: Exception) {
operationError.postValue(Event(e.message!!)) operationError.postValue(Event(e.message!!))
}finally { } finally {
operationState.postValue(Event(false)) operationState.postValue(Event(false))
operationRefresh.postValue(Event(false)) operationRefresh.postValue(Event(false))
} }

View File

@@ -15,6 +15,7 @@ import kotlinx.coroutines.launch
import java.io.IOException import java.io.IOException
const val ALL_LOADED = "all_loaded" const val ALL_LOADED = "all_loaded"
class WorldViewModel( class WorldViewModel(
private val locationProvider: LocationProvider, private val locationProvider: LocationProvider,
private val repository: Repository private val repository: Repository
@@ -40,7 +41,7 @@ class WorldViewModel(
} }
} }
fun getSingleLocation(locationName: String){ fun getSingleLocation(locationName: String) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
val entity = repository.getSingleWeather(locationName) val entity = repository.getSingleWeather(locationName)
val item = WeatherDisplay(entity) val item = WeatherDisplay(entity)
@@ -49,7 +50,7 @@ class WorldViewModel(
} }
fun fetchDataForSingleLocation(locationName: String) { fun fetchDataForSingleLocation(locationName: String) {
if (!repository.isSearchValid(locationName)){ if (!repository.isSearchValid(locationName)) {
operationRefresh.postValue(Event(false)) operationRefresh.postValue(Event(false))
return return
} }
@@ -72,7 +73,7 @@ class WorldViewModel(
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
operationState.postValue(Event(true)) operationState.postValue(Event(true))
// Check if location exists // Check if location exists
if (repository.getSavedLocations().contains(locationName)){ if (repository.getSavedLocations().contains(locationName)) {
operationError.postValue(Event("$locationName already exists")) operationError.postValue(Event("$locationName already exists"))
return@launch return@launch
} }
@@ -82,8 +83,12 @@ class WorldViewModel(
val entityItem = createWeatherEntity(locationName) val entityItem = createWeatherEntity(locationName)
// retrieved location name // retrieved location name
val retrievedLocation = locationProvider.getLocationNameFromLatLong(entityItem.weather.lat, entityItem.weather.lon, LocationType.City) val retrievedLocation = locationProvider.getLocationNameFromLatLong(
if (repository.getSavedLocations().contains(retrievedLocation)){ entityItem.weather.lat,
entityItem.weather.lon,
LocationType.City
)
if (repository.getSavedLocations().contains(retrievedLocation)) {
operationError.postValue(Event("$retrievedLocation already exists")) operationError.postValue(Event("$retrievedLocation already exists"))
return@launch return@launch
} }
@@ -101,7 +106,7 @@ class WorldViewModel(
} }
fun fetchAllLocations() { fun fetchAllLocations() {
if (!repository.isSearchValid(ALL_LOADED)){ if (!repository.isSearchValid(ALL_LOADED)) {
operationRefresh.postValue(Event(false)) operationRefresh.postValue(Event(false))
return return
} }
@@ -117,7 +122,8 @@ class WorldViewModel(
val entity = createWeatherEntity(locationName) val entity = createWeatherEntity(locationName)
list.add(entity) list.add(entity)
repository.saveLastSavedAt(locationName) repository.saveLastSavedAt(locationName)
} catch (e: IOException) { } } catch (e: IOException) {
}
} }
repository.saveWeatherListToRoom(list) repository.saveWeatherListToRoom(list)
repository.saveLastSavedAt(ALL_LOADED) repository.saveLastSavedAt(ALL_LOADED)
@@ -129,12 +135,12 @@ class WorldViewModel(
} }
} }
fun deleteLocation(locationName: String){ fun deleteLocation(locationName: String) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
operationState.postValue(Event(true)) operationState.postValue(Event(true))
try { try {
val success = repository.deleteSavedWeatherEntry(locationName) val success = repository.deleteSavedWeatherEntry(locationName)
if (!success){ if (!success) {
operationError.postValue(Event("Failed to delete")) operationError.postValue(Event("Failed to delete"))
} }
} catch (e: IOException) { } catch (e: IOException) {
@@ -158,8 +164,9 @@ class WorldViewModel(
private suspend fun createWeatherEntity(locationName: String): EntityItem { private suspend fun createWeatherEntity(locationName: String): EntityItem {
val weather = getWeather(locationName) val weather = getWeather(locationName)
val location = locationProvider.getLocationNameFromLatLong(weather.lat, weather.lon, LocationType.City) val location =
locationProvider.getLocationNameFromLatLong(weather.lat, weather.lon, LocationType.City)
val fullWeather = createFullWeather(weather, location) val fullWeather = createFullWeather(weather, location)
return createWeatherEntity(location,fullWeather) return createWeatherEntity(location, fullWeather)
} }
} }

View File

@@ -5,7 +5,7 @@ import com.appttude.h_mal.atlas_weather.data.network.response.forecast.WeatherRe
import com.appttude.h_mal.atlas_weather.data.room.entity.EntityItem import com.appttude.h_mal.atlas_weather.data.room.entity.EntityItem
import com.appttude.h_mal.atlas_weather.model.weather.FullWeather import com.appttude.h_mal.atlas_weather.model.weather.FullWeather
abstract class WeatherViewModel : ViewModel(){ abstract class WeatherViewModel : ViewModel() {
fun createFullWeather( fun createFullWeather(
weather: WeatherResponse, weather: WeatherResponse,
@@ -20,7 +20,7 @@ abstract class WeatherViewModel : ViewModel(){
fun createWeatherEntity( fun createWeatherEntity(
locationId: String, locationId: String,
weather: FullWeather weather: FullWeather
): EntityItem{ ): EntityItem {
weather.apply { weather.apply {
locationString = locationId locationString = locationId
} }

View File

@@ -8,7 +8,6 @@ import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider import android.appwidget.AppWidgetProvider
import android.content.ComponentName import android.content.ComponentName
import android.content.Intent import android.content.Intent
import android.os.Build
import android.widget.RemoteViews import android.widget.RemoteViews
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
@@ -43,11 +42,12 @@ abstract class BaseWidgetServiceIntentClass<T : AppWidgetProvider> : JobIntentSe
val idArray = intArrayOf(appWidgetId) val idArray = intArrayOf(appWidgetId)
intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray) intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { return PendingIntent.getBroadcast(
PendingIntent.getBroadcast(this, seconds, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) this,
} else { seconds,
PendingIntent.getBroadcast(this, seconds, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT) intentUpdate,
} PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
)
} }
/** /**

View File

@@ -11,7 +11,11 @@ import com.appttude.h_mal.atlas_weather.widget.WidgetJobServiceIntent.Companion.
*/ */
class NewAppWidget : AppWidgetProvider() { class NewAppWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
super.onUpdate(context, appWidgetManager, appWidgetIds) super.onUpdate(context, appWidgetManager, appWidgetIds)
loadWidget(context) loadWidget(context)
@@ -23,9 +27,9 @@ class NewAppWidget : AppWidgetProvider() {
loadWidget(context) loadWidget(context)
} }
override fun onDisabled(context: Context) { } override fun onDisabled(context: Context) {}
private fun loadWidget(context: Context){ private fun loadWidget(context: Context) {
val mIntent = Intent(context, WidgetJobServiceIntent::class.java) val mIntent = Intent(context, WidgetJobServiceIntent::class.java)
enqueueWork(context, mIntent) enqueueWork(context, mIntent)
} }

View File

@@ -10,17 +10,16 @@ import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.icu.text.SimpleDateFormat import android.icu.text.SimpleDateFormat
import android.os.PowerManager import android.os.PowerManager
import android.widget.RemoteViews import android.widget.RemoteViews
import android.os.Build
import androidx.core.app.ActivityCompat.checkSelfPermission import androidx.core.app.ActivityCompat.checkSelfPermission
import com.appttude.h_mal.atlas_weather.R import com.appttude.h_mal.atlas_weather.R
import com.appttude.h_mal.atlas_weather.widget.WidgetState.*
import com.appttude.h_mal.atlas_weather.widget.WidgetState.Companion.getWidgetState
import com.appttude.h_mal.atlas_weather.helper.ServicesHelper import com.appttude.h_mal.atlas_weather.helper.ServicesHelper
import com.appttude.h_mal.atlas_weather.model.widget.InnerWidgetCellData import com.appttude.h_mal.atlas_weather.model.widget.InnerWidgetCellData
import com.appttude.h_mal.atlas_weather.model.widget.WidgetWeatherCollection import com.appttude.h_mal.atlas_weather.model.widget.WidgetWeatherCollection
import com.appttude.h_mal.atlas_weather.ui.MainActivity import com.appttude.h_mal.atlas_weather.ui.MainActivity
import com.appttude.h_mal.atlas_weather.utils.isInternetAvailable import com.appttude.h_mal.atlas_weather.utils.isInternetAvailable
import com.appttude.h_mal.atlas_weather.utils.tryOrNullSuspended import com.appttude.h_mal.atlas_weather.utils.tryOrNullSuspended
import com.appttude.h_mal.atlas_weather.widget.WidgetState.*
import com.appttude.h_mal.atlas_weather.widget.WidgetState.Companion.getWidgetState
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -34,6 +33,7 @@ import java.util.*
* Implementation of a JobIntentService used for home screen widget * Implementation of a JobIntentService used for home screen widget
*/ */
const val HALF_DAY = 43200000L const val HALF_DAY = 43200000L
class WidgetJobServiceIntent : BaseWidgetServiceIntentClass<NewAppWidget>() { class WidgetJobServiceIntent : BaseWidgetServiceIntentClass<NewAppWidget>() {
private val kodein = LateInitKodein() private val kodein = LateInitKodein()
@@ -167,6 +167,7 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass<NewAppWidget>() {
} }
} }
@SuppressLint("DiscouragedApi")
private fun loadCells( private fun loadCells(
appWidgetId: Int, appWidgetId: Int,
remoteViews: RemoteViews, remoteViews: RemoteViews,
@@ -189,7 +190,7 @@ class WidgetJobServiceIntent : BaseWidgetServiceIntentClass<NewAppWidget>() {
} }
private fun setLastUpdated(views: RemoteViews, timeStamp: Long?) { private fun setLastUpdated(views: RemoteViews, timeStamp: Long?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && timeStamp != null) { if (timeStamp != null) {
val difference = System.currentTimeMillis().minus(timeStamp) val difference = System.currentTimeMillis().minus(timeStamp)
val status = if (difference > HALF_DAY) { val status = if (difference > HALF_DAY) {

View File

@@ -1,34 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#000000" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<path android:fillColor="@android:color/black" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/> android:tint="#000000"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/black"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</vector> </vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="128dp" android:tint="#FFFFFF" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="128dp"
android:width="128dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="128dp"
<path android:fillColor="@android:color/white" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4c-1.48,0 -2.85,0.43 -4.01,1.17l1.46,1.46C10.21,6.23 11.08,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3 0,1.13 -0.64,2.11 -1.56,2.62l1.45,1.45C23.16,18.16 24,16.68 24,15c0,-2.64 -2.05,-4.78 -4.65,-4.96zM3,5.27l2.75,2.74C2.56,8.15 0,10.77 0,14c0,3.31 2.69,6 6,6h11.73l2,2L21,20.73 4.27,4 3,5.27zM7.73,10l8,8H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h1.73z"/> android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4c-1.48,0 -2.85,0.43 -4.01,1.17l1.46,1.46C10.21,6.23 11.08,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3 0,1.13 -0.64,2.11 -1.56,2.62l1.45,1.45C23.16,18.16 24,16.68 24,15c0,-2.64 -2.05,-4.78 -4.65,-4.96zM3,5.27l2.75,2.74C2.56,8.15 0,10.77 0,14c0,3.31 2.69,6 6,6h11.73l2,2L21,20.73 4.27,4 3,5.27zM7.73,10l8,8H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h1.73z" />
</vector> </vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<path android:fillColor="@android:color/white" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h0.71C7.37,7.69 9.48,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3s-1.34,3 -3,3z"/> android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h0.71C7.37,7.69 9.48,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3s-1.34,3 -3,3z" />
</vector> </vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<path android:fillColor="@android:color/white" android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"/> android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z" />
</vector> </vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z"/> android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z" />
</vector> </vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<path android:fillColor="@android:color/white" android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/> android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z" />
</vector> </vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 978 B

View File

@@ -1,24 +1,25 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="94dp" android:width="68dp"
android:height="275dp" android:height="200dp"
android:viewportWidth="94.0" android:viewportWidth="94.0"
android:viewportHeight="275.0"> android:viewportHeight="275.0">
<path <path
android:fillColor="#FF000000" android:fillColor="#FF000000"
android:pathData="M75.1515587070021,188.25562584016225 V29.53767503746845 c0,-14.982132974790945 -11.77674089383421,-26.46075177701539 -27.147989048437097,-26.46075177701539 c-15.371248154602887,0 -27.147989048437097,12.354497345366072 -27.147989048437097,26.46075177701539 v158.672312920709 c-10.878114078642042,7.929466747673202 -18.067128600179394,21.15938164747398 -18.067128600179394,35.2656360791233 c0,24.66289582004048 19.911678378731743,44.07052038123121 android:pathData="M75.1515587070021,188.25562584016225 V29.53767503746845 c0,-14.982132974790945 -11.77674089383421,-26.46075177701539 -27.147989048437097,-26.46075177701539 c-15.371248154602887,0 -27.147989048437097,12.354497345366072 -27.147989048437097,26.46075177701539 v158.672312920709 c-10.878114078642042,7.929466747673202 -18.067128600179394,21.15938164747398 -18.067128600179394,35.2656360791233 c0,24.66289582004048 19.911678378731743,44.07052038123121
45.21511764861649,44.07052038123121 c25.303439269884752,0 45.21464468713481,-19.407624561190733 45.21464468713481,-44.07052038123121 C93.21821434569982,209.36936960565146 85.98237663747612,196.1850925878354 75.1515587070021,188.25562584016225 zM48.003569658565006,258.78689799840873 c-19.911678378731743,0 -36.1815533485268,-15.857089540518738 -36.1815533485268,-35.2656360791233 c0,-13.229914899800779 7.236310669705359,-24.66289582004048 18.067128600179394,-30.83922251530968 45.21511764861649,44.07052038123121 c25.303439269884752,0 45.21464468713481,-19.407624561190733 45.21464468713481,-44.07052038123121 C93.21821434569982,209.36936960565146 85.98237663747612,196.1850925878354 75.1515587070021,188.25562584016225 zM48.003569658565006,258.78689799840873 c-19.911678378731743,0 -36.1815533485268,-15.857089540518738 -36.1815533485268,-35.2656360791233 c0,-13.229914899800779 7.236310669705359,-24.66289582004048 18.067128600179394,-30.83922251530968
V29.53767503746845 c0,-9.680762845249534 8.134937484897527,-17.60976860421582 18.067128600179394,-17.60976860421582 s18.06665563869771,7.929005758966285 18.06665563869771,17.60976860421582 v163.09734351840189 c10.878114078642042,6.177248672683036 18.06760156166107,17.610229592922735 18.06760156166107,30.840144492723518 C84.1851230070918,242.88278760978457 67.91477507581507,258.78689799840873 48.003569658565006,258.78689799840873 z"/> V29.53767503746845 c0,-9.680762845249534 8.134937484897527,-17.60976860421582 18.067128600179394,-17.60976860421582 s18.06665563869771,7.929005758966285 18.06665563869771,17.60976860421582 v163.09734351840189 c10.878114078642042,6.177248672683036 18.06760156166107,17.610229592922735 18.06760156166107,30.840144492723518 C84.1851230070918,242.88278760978457 67.91477507581507,258.78689799840873 48.003569658565006,258.78689799840873 z" />
<path <path
android:name="inner" android:name="inner"
android:fillColor="#ff0000" android:fillColor="#ff0000"
android:pathData="M305.949,424.6c0-1.9,0-1.9,0-3.799v-95.602c0-11.5-7.6-19.1-19.099-19.1c-11.5,0-19.1,7.6-19.1,19.1v95.602 android:pathData="M305.949,424.6c0-1.9,0-1.9,0-3.799v-95.602c0-11.5-7.6-19.1-19.099-19.1c-11.5,0-19.1,7.6-19.1,19.1v95.602
c0,1.898,0,1.898,0,3.799c-23,7.701-38.2,28.701-38.2,53.5c0,32.5,24.9,57.4,57.4,57.4c32.499,0,57.399-24.9,57.399-57.4 c0,1.898,0,1.898,0,3.799c-23,7.701-38.2,28.701-38.2,53.5c0,32.5,24.9,57.4,57.4,57.4c32.499,0,57.399-24.9,57.399-57.4
C344.25,453.301,328.949,432.301,305.949,424.6z"/> C344.25,453.301,328.949,432.301,305.949,424.6z" />
<path android:fillColor="#000000" <path
android:pathData="M75.1515587070021,188.25562584016225 V29.53767503746845 c0,-14.982132974790945 -11.77674089383421,-26.46075177701539 -27.147989048437097,-26.46075177701539 c-15.371248154602887,0 -27.147989048437097,12.354497345366072 -27.147989048437097,26.46075177701539 v158.672312920709 c-10.878114078642042,7.929466747673202 -18.067128600179394,21.15938164747398 -18.067128600179394,35.2656360791233 c0,24.66289582004048 19.911678378731743,44.07052038123121 45.21511764861649,44.07052038123121 c25.303439269884752,0 45.21464468713481,-19.407624561190733 45.21464468713481,-44.07052038123121 C93.21821434569982,209.36936960565146 85.98237663747612,196.1850925878354 75.1515587070021,188.25562584016225 zM48.003569658565006,258.78689799840873 c-19.911678378731743,0 -36.1815533485268,-15.857089540518738 -36.1815533485268,-35.2656360791233 c0,-13.229914899800779 7.236310669705359,-24.66289582004048 18.067128600179394,-30.83922251530968 V29.53767503746845 c0,-9.680762845249534 8.134937484897527,-17.60976860421582 18.067128600179394,-17.60976860421582 s18.06665563869771,7.929005758966285 18.06665563869771,17.60976860421582 v163.09734351840189 c10.878114078642042,6.177248672683036 18.06760156166107,17.610229592922735 18.06760156166107,30.840144492723518 C84.1851230070918,242.88278760978457 67.91477507581507,258.78689799840873 48.003569658565006,258.78689799840873 z"/> android:fillColor="#000000"
android:pathData="M75.1515587070021,188.25562584016225 V29.53767503746845 c0,-14.982132974790945 -11.77674089383421,-26.46075177701539 -27.147989048437097,-26.46075177701539 c-15.371248154602887,0 -27.147989048437097,12.354497345366072 -27.147989048437097,26.46075177701539 v158.672312920709 c-10.878114078642042,7.929466747673202 -18.067128600179394,21.15938164747398 -18.067128600179394,35.2656360791233 c0,24.66289582004048 19.911678378731743,44.07052038123121 45.21511764861649,44.07052038123121 c25.303439269884752,0 45.21464468713481,-19.407624561190733 45.21464468713481,-44.07052038123121 C93.21821434569982,209.36936960565146 85.98237663747612,196.1850925878354 75.1515587070021,188.25562584016225 zM48.003569658565006,258.78689799840873 c-19.911678378731743,0 -36.1815533485268,-15.857089540518738 -36.1815533485268,-35.2656360791233 c0,-13.229914899800779 7.236310669705359,-24.66289582004048 18.067128600179394,-30.83922251530968 V29.53767503746845 c0,-9.680762845249534 8.134937484897527,-17.60976860421582 18.067128600179394,-17.60976860421582 s18.06665563869771,7.929005758966285 18.06665563869771,17.60976860421582 v163.09734351840189 c10.878114078642042,6.177248672683036 18.06760156166107,17.610229592922735 18.06760156166107,30.840144492723518 C84.1851230070918,242.88278760978457 67.91477507581507,258.78689799840873 48.003569658565006,258.78689799840873 z" />
<path <path
android:name="inner" android:name="inner"
android:fillColor="#ff0000" android:fillColor="#ff0000"
android:pathData="M57.03666099717303,198.81272821726031 c0,-0.8758785431416244 0,-0.8758785431416244 0,-1.7512960975763323 v-44.07144235864505 c0,-5.301370129541411 -3.5945072607686748,-8.80488430210791 -9.033091338608017,-8.80488430210791 c-5.439057039321021,0 -9.033564300089697,3.503514172566498 -9.033564300089697,8.80488430210791 v44.07144235864505 c0,0.8749565657277916 0,0.8749565657277916 0,1.7512960975763323 c-10.878114078642042,3.550074031965079 -18.067128600179394,13.230836877214614 -18.067128600179394,24.66289582004048 c0,14.982132974790945 11.77674089383421,26.46075177701539 27.147989048437097,26.46075177701539 c15.370775193121208,0 27.147516086955417,-11.478618802224446 27.147516086955417,-26.46075177701539 C75.1515587070021,212.04356509447487 67.91477507581507,202.36280224922535 57.03666099717303,198.81272821726031 z"/> android:pathData="M57.03666099717303,198.81272821726031 c0,-0.8758785431416244 0,-0.8758785431416244 0,-1.7512960975763323 v-44.07144235864505 c0,-5.301370129541411 -3.5945072607686748,-8.80488430210791 -9.033091338608017,-8.80488430210791 c-5.439057039321021,0 -9.033564300089697,3.503514172566498 -9.033564300089697,8.80488430210791 v44.07144235864505 c0,0.8749565657277916 0,0.8749565657277916 0,1.7512960975763323 c-10.878114078642042,3.550074031965079 -18.067128600179394,13.230836877214614 -18.067128600179394,24.66289582004048 c0,14.982132974790945 11.77674089383421,26.46075177701539 27.147989048437097,26.46075177701539 c15.370775193121208,0 27.147516086955417,-11.478618802224446 27.147516086955417,-26.46075177701539 C75.1515587070021,212.04356509447487 67.91477507581507,202.36280224922535 57.03666099717303,198.81272821726031 z" />
</vector> </vector>

View File

@@ -3,8 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical">
tools:context="com.appttude.h_mal.atlas_weather.ui.world.AddLocationFragment">
<LinearLayout <LinearLayout
@@ -18,20 +17,21 @@
<EditText <EditText
android:id="@+id/location_name_tv" android:id="@+id/location_name_tv"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="0dp"
android:layout_weight="2" android:layout_weight="2"
android:ems="10" android:ems="10"
android:hint="@string/location_name" android:hint="@string/location_name"
android:inputType="textPersonName" android:inputType="textPersonName"
android:maxLines="2" android:maxLines="2"
tools:text="Greater London"/> tools:text="Greater London"
android:autofillHints="addressLocality" />
<Button <Button
android:id="@+id/submit" android:id="@+id/submit"
style="?android:attr/borderlessButtonStyle" style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="right" android:layout_gravity="end"
android:text="@string/submit" android:text="@string/submit"
android:textColor="#ffffff" android:textColor="#ffffff"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -44,11 +44,12 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@android:color/black" android:background="@android:color/black"
android:visibility="gone"> android:visibility="gone">
<ProgressBar <ProgressBar
android:layout_gravity="center"
style="?android:attr/progressBarStyle" style="?android:attr/progressBarStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout> </FrameLayout>

View File

@@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -15,13 +18,16 @@
<FrameLayout style="@style/icon_frame_style"> <FrameLayout style="@style/icon_frame_style">
<ImageView <ImageView
android:src="@drawable/somethingnew" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:contentDescription="@string/temperature"
android:src="@drawable/somethingnew" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="2"> android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -41,16 +47,16 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Max: " /> android:text="@string/max_header" />
<TextView <TextView
android:id="@+id/maxtemp" android:id="@+id/maxtemp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="85%" tools:text="85%" />
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -59,16 +65,17 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Average: " /> android:text="@string/average_header" />
<TextView <TextView
android:id="@+id/averagetemp" android:id="@+id/averagetemp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="11mm" tools:ignore="InOrMmUsage"
/> tools:text="11mm" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -77,15 +84,15 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Min: " /> android:text="@string/min_header" />
<TextView <TextView
android:id="@+id/minimumtemp" android:id="@+id/minimumtemp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="11mm" tools:ignore="InOrMmUsage"
/> tools:text="11mm" />
</LinearLayout> </LinearLayout>
@@ -94,21 +101,23 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<FrameLayout <FrameLayout style="@style/icon_frame_style">
style="@style/icon_frame_style">
<ImageView <ImageView
android:src="@drawable/breeze" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:contentDescription="@string/image_string"
android:src="@drawable/breeze" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_weight="2"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -118,41 +127,42 @@
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_weight="3"> android:layout_weight="3">
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Wind: " /> android:text="@string/wind_header" />
<TextView <TextView
android:id="@+id/windtext" android:id="@+id/windtext"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="7mph" tools:text="7mph" />
/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<FrameLayout <FrameLayout style="@style/icon_frame_style">
style="@style/icon_frame_style">
<ImageView <ImageView
android:src="@drawable/water_drop" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:contentDescription="@string/image_string"
android:src="@drawable/water_drop" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_weight="2"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -172,16 +182,16 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Humidity: " /> android:text="@string/humidity_header" />
<TextView <TextView
android:id="@+id/humiditytext" android:id="@+id/humiditytext"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="85%" tools:text="85%" />
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -190,15 +200,15 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Precip: " /> android:text="@string/precip_header" />
<TextView <TextView
android:id="@+id/preciptext" android:id="@+id/preciptext"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="11mm" tools:ignore="InOrMmUsage"
/> tools:text="11mm" />
</LinearLayout> </LinearLayout>
@@ -207,21 +217,24 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<FrameLayout <FrameLayout style="@style/icon_frame_style">
style="@style/icon_frame_style">
<ImageView <ImageView
android:src="@drawable/cloud_symbol" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:contentDescription="@string/image_string"
android:src="@drawable/cloud_symbol" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_weight="2"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -241,14 +254,14 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Cloud:" /> android:text="@string/cloud_header" />
<TextView <TextView
android:id="@+id/cloudtext" android:id="@+id/cloudtext"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="06:12pm" /> tools:text="06:12pm" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@@ -256,21 +269,24 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<FrameLayout <FrameLayout style="@style/icon_frame_style">
style="@style/icon_frame_style">
<ImageView <ImageView
android:src="@drawable/sunrise" style="@style/icon_style__further_details"
style="@style/icon_style__further_deatils" /> android:contentDescription="@string/image_string"
android:src="@drawable/sunrise" />
</FrameLayout> </FrameLayout>
<RelativeLayout <RelativeLayout
android:layout_weight="2"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_weight="2">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -290,15 +306,14 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="UV: " /> android:text="@string/uv_header" />
<TextView <TextView
android:id="@+id/uvtext" android:id="@+id/uvtext"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="7" tools:text="7" />
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@@ -309,15 +324,16 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Sunrise:" /> android:text="@string/sunrise_header" />
<TextView <TextView
android:id="@+id/sunrisetext" android:id="@+id/sunrisetext"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="05:30am" /> tools:text="05:30am" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -326,15 +342,14 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:layout_weight="2"
android:text="Sunset:" /> android:text="@string/sunset_header" />
<TextView <TextView
android:id="@+id/sunsettext" android:id="@+id/sunsettext"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="06:12pm" tools:text="06:12pm" />
/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -16,7 +15,7 @@
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:popupTheme="@style/AppTheme.PopupOverlay" app:popupTheme="@style/AppTheme.PopupOverlay"
tools:title="Atlas Weather"/> tools:title="Atlas Weather" />
<com.google.android.material.bottomnavigation.BottomNavigationView <com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view" android:id="@+id/nav_view"
@@ -39,7 +38,7 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" app:layout_constraintTop_toBottomOf="@id/toolbar"
tools:layout="@layout/fragment_home"/> tools:layout="@layout/fragment_home" />
<ProgressBar <ProgressBar
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@@ -1,31 +1,27 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp" android:layout_marginLeft="24dp"
android:layout_marginTop="6dp" android:layout_marginTop="6dp"
android:layout_marginRight="24dp" android:layout_marginRight="24dp"
android:layout_marginBottom="6dp" android:layout_marginBottom="6dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<ImageView <ImageView
android:id="@+id/db_icon" android:id="@+id/db_icon"
android:layout_width="64dp" android:layout_width="64dp"
android:layout_height="64dp" android:layout_height="64dp"
android:contentDescription="@string/icon"
tools:src="@drawable/cloud_symbol" tools:src="@drawable/cloud_symbol"
tools:tint="@color/colour_one"/> tools:tint="@color/colour_one" />
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginLeft="15dp" android:layout_marginStart="15dp"
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical"> android:orientation="vertical">
@@ -49,7 +45,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginRight="4dp" android:layout_marginEnd="4dp"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@@ -64,9 +60,6 @@
android:id="@+id/db_temp_unit" android:id="@+id/db_temp_unit"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="°" /> android:text="@string/degree_sign" />
</LinearLayout> </LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

Some files were not shown because too many files have changed in this diff Show More