This commit is contained in:
202310715128 ARIF NURKHAYAN 2025-12-28 20:22:07 +07:00
parent 68246777fd
commit 92c76b21ea
42 changed files with 749 additions and 406 deletions

3
.idea/.gitignore generated vendored
View File

@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

1
.idea/.name generated Normal file
View File

@ -0,0 +1 @@
WeatherDemo

View File

@ -4,10 +4,10 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-10-31T13:55:47.201920Z"> <DropdownSelection timestamp="2025-12-18T06:25:18.162928Z">
<Target type="DEFAULT_BOOT"> <Target type="DEFAULT_BOOT">
<handle> <handle>
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/khaliqozil/.android/avd/Pixel_6_API_34.avd" /> <DeviceId pluginId="PhysicalDevice" identifier="serial=325F50919896" />
</handle> </handle>
</Target> </Target>
</DropdownSelection> </DropdownSelection>

13
.idea/deviceManager.xml generated Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceTable">
<option name="columnSorters">
<list>
<ColumnSorterState>
<option name="column" value="Name" />
<option name="order" value="ASCENDING" />
</ColumnSorterState>
</list>
</option>
</component>
</project>

6
.idea/kotlinc.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="2.0.21" />
</component>
</project>

1
.idea/misc.xml generated
View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -1,4 +0,0 @@
kotlin version: 2.0.21
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready

View File

@ -1,6 +1,7 @@
plugins { plugins {
alias(libs.plugins.android.application) alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.android)
id("com.google.gms.google-services")
} }
android { android {
@ -37,6 +38,7 @@ android {
dependencies { dependencies {
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.material) implementation(libs.material)
@ -46,6 +48,9 @@ dependencies {
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
implementation("com.google.android.material:material:1.8.0")
implementation("androidx.cardview:cardview:1.0.0")
implementation ("com.google.android.material:material:1.8.0") implementation ("com.google.android.material:material:1.8.0")
@ -57,4 +62,14 @@ dependencies {
implementation ("com.squareup.okhttp3:logging-interceptor:4.10.0") implementation ("com.squareup.okhttp3:logging-interceptor:4.10.0")
implementation ("androidx.activity:activity-ktx:1.7.2") implementation ("androidx.activity:activity-ktx:1.7.2")
implementation("androidx.recyclerview:recyclerview:1.2.1")
// Firebase SDK
implementation("com.google.firebase:firebase-auth:21.1.0") // Firebase Authentication untuk login
implementation("com.google.firebase:firebase-database:20.0.5") // Firebase Realtime Database
// Firebase BoM (Bill of Materials)
implementation(platform("com.google.firebase:firebase-bom:30.3.1")) // Pastikan semua Firebase SDK menggunakan versi yang kompatibel
} }
apply(plugin = "com.google.gms.google-services")

View File

@ -2,32 +2,39 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<!-- Internet permission for API calls -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- Network state permission for checking connectivity -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher" android:icon="@drawable/ic_launcher_foreground"
android:roundIcon="@drawable/ic_launcher_foreground"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.WeatherDemo" android:theme="@style/Theme.WeatherDemo"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".ui.MainActivity" android:name=".ui.LoginActivity"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".ui.MainActivity"
android:exported="true" />
<!-- WAJIB: ChatActivity -->
<activity
android:name=".ui.ChatActivity"
android:exported="true" />
</application> </application>
</manifest> </manifest>

View File

@ -0,0 +1,9 @@
package com.example.weatherdemo.data
data class Message(
var id: String = "",
var username: String = "",
var message: String = "",
val time: String = "",
var timestamp: Long = 0L
)

View File

@ -20,7 +20,7 @@ class WeatherRepository(private val apiService: WeatherApiService) {
return try { return try {
// Make API call // Make API call
val response: Response<WeatherResponse> = apiService.getCurrentWeather( val response: Response<WeatherResponse> = apiService.getCurrentWeather(
key = "YOUR_API_KEY", // API key key = "822615b3cef1437bb0202739251712", // API key
query = location query = location
) )

View File

@ -0,0 +1,84 @@
package com.example.weatherdemo.ui
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.weatherdemo.R
import com.example.weatherdemo.ui.adapter.ChatAdapter
import com.example.weatherdemo.utils.FirebaseUtils
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
class ChatActivity : AppCompatActivity() {
private lateinit var etMessage: EditText
private lateinit var btnSend: Button
private lateinit var recyclerView: RecyclerView
private lateinit var chatAdapter: ChatAdapter
private lateinit var username: String // username user aktif
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat)
// Toolbar + tombol back
val toolbar = findViewById<Toolbar>(R.id.toolbarChat)
setSupportActionBar(toolbar)
toolbar.setNavigationOnClickListener { finish() }
// ✅ Ambil username dari Intent
username = intent.getStringExtra("username") ?: "Guest"
etMessage = findViewById(R.id.etMessage)
btnSend = findViewById(R.id.btnSend)
recyclerView = findViewById(R.id.recyclerView)
val layoutManager = LinearLayoutManager(this).apply {
stackFromEnd = true
}
recyclerView.layoutManager = layoutManager
// 🔥 WAJIB kirim username ke ChatAdapter
chatAdapter = ChatAdapter(username)
recyclerView.adapter = chatAdapter
btnSend.setOnClickListener {
val messageText = etMessage.text.toString().trim()
if (messageText.isNotEmpty()) {
val time = SimpleDateFormat(
"HH:mm",
Locale.getDefault()
).format(Date())
FirebaseUtils.sendMessage(
username = username,
message = messageText,
time = time
)
etMessage.setText("")
}
}
}
override fun onStart() {
super.onStart()
FirebaseUtils.getMessages { messages ->
chatAdapter.submitList(messages)
if (messages.isNotEmpty()) {
recyclerView.post {
recyclerView.scrollToPosition(messages.size - 1)
}
}
}
}
}

View File

@ -0,0 +1,39 @@
package com.example.weatherdemo.ui
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.weatherdemo.R
class LoginActivity : AppCompatActivity() {
private lateinit var etUsername: EditText
private lateinit var btnLogin: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
etUsername = findViewById(R.id.etUsername)
btnLogin = findViewById(R.id.btnLogin)
btnLogin.setOnClickListener {
val username = etUsername.text.toString().trim()
if (username.isNotEmpty()) {
val intent = Intent(this, MainActivity::class.java)
// ✅ FIX: key KONSISTEN
intent.putExtra("username", username)
startActivity(intent)
finish()
} else {
Toast.makeText(this, "Please enter a username", Toast.LENGTH_SHORT).show()
}
}
}
}

View File

@ -1,15 +1,18 @@
package com.example.weatherdemo.ui package com.example.weatherdemo.ui
import android.content.Context import android.content.Context
import androidx.appcompat.app.AppCompatActivity import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.EditText import android.widget.EditText
import android.widget.LinearLayout
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.example.weatherdemo.R import com.example.weatherdemo.R
import com.example.weatherdemo.data.api.RetrofitInstance import com.example.weatherdemo.data.api.RetrofitInstance
@ -19,38 +22,36 @@ import com.example.weatherdemo.viewmodel.WeatherViewModel
import com.example.weatherdemo.viewmodel.WeatherViewModelFactory import com.example.weatherdemo.viewmodel.WeatherViewModelFactory
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.floatingactionbutton.FloatingActionButton
/**
* Main Activity class that handles UI and user interactions
* Observes ViewModel LiveData and updates UI accordingly
*/
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
// Initialize ViewModel using viewModels delegate
private val viewModel: WeatherViewModel by viewModels { private val viewModel: WeatherViewModel by viewModels {
// Create ViewModel with repository dependency WeatherViewModelFactory(WeatherRepository(RetrofitInstance.apiService))
WeatherViewModelFactory(
WeatherRepository(RetrofitInstance.apiService)
)
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
// Initialize UI components // ✅ FIX DI SINI SAJA
val username = intent.getStringExtra("username") ?: "Guest"
val tvWelcomeMessage = findViewById<TextView>(R.id.tvWelcomeMessage)
tvWelcomeMessage.text = "Welcome, $username!"
// FAB chat → kirim username ke ChatActivity
findViewById<FloatingActionButton>(R.id.fabChat).setOnClickListener {
val i = Intent(this, ChatActivity::class.java)
i.putExtra("username", username)
startActivity(i)
}
initViews() initViews()
// Set up observers for LiveData
setupObservers() setupObservers()
// Load default location weather
viewModel.fetchWeatherData("London") viewModel.fetchWeatherData("London")
} }
/**
* Initializes UI components and sets up click listeners
*/
private fun initViews() { private fun initViews() {
val btnSearch = findViewById<MaterialButton>(R.id.btnSearch) val btnSearch = findViewById<MaterialButton>(R.id.btnSearch)
val etSearch = findViewById<EditText>(R.id.etSearch) val etSearch = findViewById<EditText>(R.id.etSearch)
@ -58,9 +59,7 @@ class MainActivity : AppCompatActivity() {
btnSearch.setOnClickListener { btnSearch.setOnClickListener {
val location = etSearch.text.toString().trim() val location = etSearch.text.toString().trim()
if (location.isNotEmpty()) { if (location.isNotEmpty()) {
// Hide keyboard
hideKeyboard() hideKeyboard()
// Fetch weather data for entered location
viewModel.fetchWeatherData(location) viewModel.fetchWeatherData(location)
} else { } else {
Toast.makeText(this, "Please enter a location", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Please enter a location", Toast.LENGTH_SHORT).show()
@ -68,31 +67,21 @@ class MainActivity : AppCompatActivity() {
} }
} }
/**
* Sets up observers for ViewModel LiveData
* Observes weather data, loading state, and error messages
*/
private fun setupObservers() { private fun setupObservers() {
// Observe weather data changes
viewModel.weatherData.observe(this, Observer { weatherData -> viewModel.weatherData.observe(this, Observer { weatherData ->
weatherData?.let { weatherData?.let { updateWeatherUI(it) }
updateWeatherUI(it)
}
}) })
// Observe loading state
viewModel.isLoading.observe(this, Observer { isLoading -> viewModel.isLoading.observe(this, Observer { isLoading ->
val progressBar = findViewById<ProgressBar>(R.id.progressBar) findViewById<ProgressBar>(R.id.progressBar).visibility =
progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE if (isLoading) View.VISIBLE else View.GONE
}) })
// Observe error messages
viewModel.errorMessage.observe(this, Observer { errorMessage -> viewModel.errorMessage.observe(this, Observer { errorMessage ->
val tvError = findViewById<TextView>(R.id.tvError) val tvError = findViewById<TextView>(R.id.tvError)
if (errorMessage.isNotEmpty()) { if (errorMessage.isNotEmpty()) {
tvError.text = errorMessage tvError.text = errorMessage
tvError.visibility = View.VISIBLE tvError.visibility = View.VISIBLE
// Hide weather card on error
findViewById<MaterialCardView>(R.id.weatherCard).visibility = View.GONE findViewById<MaterialCardView>(R.id.weatherCard).visibility = View.GONE
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show() Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show()
} else { } else {
@ -101,10 +90,6 @@ class MainActivity : AppCompatActivity() {
}) })
} }
/**
* Updates UI with weather data
* @param weatherResponse The weather data to display
*/
private fun updateWeatherUI(weatherResponse: WeatherResponse) { private fun updateWeatherUI(weatherResponse: WeatherResponse) {
val weatherCard = findViewById<MaterialCardView>(R.id.weatherCard) val weatherCard = findViewById<MaterialCardView>(R.id.weatherCard)
val tvLocation = findViewById<TextView>(R.id.tvLocation) val tvLocation = findViewById<TextView>(R.id.tvLocation)
@ -114,7 +99,6 @@ class MainActivity : AppCompatActivity() {
val tvHumidity = findViewById<TextView>(R.id.tvHumidity) val tvHumidity = findViewById<TextView>(R.id.tvHumidity)
val tvWind = findViewById<TextView>(R.id.tvWind) val tvWind = findViewById<TextView>(R.id.tvWind)
// Update UI with weather data
tvLocation.text = "${weatherResponse.location.name}, ${weatherResponse.location.country}" tvLocation.text = "${weatherResponse.location.name}, ${weatherResponse.location.country}"
tvTemperature.text = "${weatherResponse.current.temp_c}°C" tvTemperature.text = "${weatherResponse.current.temp_c}°C"
tvCondition.text = weatherResponse.current.condition.text tvCondition.text = weatherResponse.current.condition.text
@ -122,13 +106,35 @@ class MainActivity : AppCompatActivity() {
tvHumidity.text = "${weatherResponse.current.humidity}%" tvHumidity.text = "${weatherResponse.current.humidity}%"
tvWind.text = "${weatherResponse.current.wind_kph} km/h" tvWind.text = "${weatherResponse.current.wind_kph} km/h"
// Show weather card val condition = weatherResponse.current.condition.text.lowercase()
val mainLayout = findViewById<LinearLayout>(R.id.mainLayout)
when {
condition.contains("clear") || condition.contains("sunny") -> {
weatherCard.setCardBackgroundColor(ContextCompat.getColor(this, R.color.sunny))
mainLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.sunny_background))
}
condition.contains("rain") -> {
weatherCard.setCardBackgroundColor(ContextCompat.getColor(this, R.color.rainy))
mainLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.rainy_background))
}
condition.contains("cloudy") -> {
weatherCard.setCardBackgroundColor(ContextCompat.getColor(this, R.color.cloudy))
mainLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.cloudy_background))
}
condition.contains("snow") -> {
weatherCard.setCardBackgroundColor(ContextCompat.getColor(this, R.color.snowy))
mainLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.snowy_background))
}
else -> {
weatherCard.setCardBackgroundColor(ContextCompat.getColor(this, R.color.default_weather))
mainLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.default_weather_background))
}
}
weatherCard.visibility = View.VISIBLE weatherCard.visibility = View.VISIBLE
} }
/**
* Hides the soft keyboard
*/
private fun hideKeyboard() { private fun hideKeyboard() {
val view = this.currentFocus val view = this.currentFocus
view?.let { view?.let {

View File

@ -0,0 +1,91 @@
package com.example.weatherdemo.ui.adapter
import android.graphics.Color
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
import com.example.weatherdemo.R
import com.example.weatherdemo.data.Message
class ChatAdapter(
private val currentUsername: String
) : RecyclerView.Adapter<ChatAdapter.MessageViewHolder>() {
private val messageList = mutableListOf<Message>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_message, parent, false)
return MessageViewHolder(view)
}
override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
holder.bind(messageList[position])
}
override fun getItemCount(): Int = messageList.size
fun submitList(messages: List<Message>) {
messageList.clear()
messageList.addAll(messages)
notifyDataSetChanged()
}
inner class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val container: LinearLayout =
itemView.findViewById(R.id.container)
private val cardMessage: CardView =
itemView.findViewById(R.id.cardMessage)
private val tvUsername: TextView =
itemView.findViewById(R.id.tvUsername)
private val tvMessage: TextView =
itemView.findViewById(R.id.tvMessage)
private val tvTime: TextView =
itemView.findViewById(R.id.tvTime)
fun bind(message: Message) {
tvUsername.text = message.username
tvMessage.text = message.message
tvTime.text = message.time
val params = container.layoutParams as RecyclerView.LayoutParams
if (message.username == currentUsername) {
// ================= USER SENDIRI (KANAN) =================
container.gravity = Gravity.END
params.marginStart = 100
params.marginEnd = 0
cardMessage.setCardBackgroundColor(
Color.parseColor("#DCF8C6")
)
tvUsername.visibility = View.VISIBLE // ✅ FIX UTAMA
} else {
// ================= USER LAIN (KIRI) =================
container.gravity = Gravity.START
params.marginStart = 0
params.marginEnd = 100
cardMessage.setCardBackgroundColor(
Color.parseColor("#E3F2FD")
)
tvUsername.visibility = View.VISIBLE
}
container.layoutParams = params
}
}
}

View File

@ -0,0 +1,50 @@
package com.example.weatherdemo.utils
import android.util.Log
import com.example.weatherdemo.data.Message
import com.google.firebase.database.*
object FirebaseUtils {
private val database = FirebaseDatabase.getInstance()
// ✅ node khusus untuk chat global
private val messagesRef = database.getReference("global_chat")
fun sendMessage(username: String, message: String, time: String) {
val id = messagesRef.push().key ?: return
val msg = Message(
id = id,
username = username,
message = message,
time = time,
timestamp = System.currentTimeMillis()
)
messagesRef.child(id).setValue(msg)
.addOnFailureListener { e ->
Log.e("FirebaseUtils", "sendMessage failed: ${e.message}", e)
}
}
fun getMessages(callback: (List<Message>) -> Unit) {
messagesRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val messages = mutableListOf<Message>()
for (data in snapshot.children) {
val msg = data.getValue(Message::class.java)
if (msg != null) messages.add(msg)
}
// ✅ urutkan biar chat rapi
messages.sortBy { it.timestamp }
callback(messages)
}
override fun onCancelled(error: DatabaseError) {
Log.e("FirebaseUtils", "getMessages cancelled: ${error.message}")
}
})
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -1,170 +1,74 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector
android:width="108dp"
android:height="108dp" android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108" android:viewportWidth="108"
android:viewportHeight="108"> xmlns:android="http://schemas.android.com/apk/res/android">
<path <path android:fillColor="#3DDC84"
android:fillColor="#3DDC84" android:pathData="M0,0h108v108h-108z"/>
android:pathData="M0,0h108v108h-108z" /> <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:pathData="M9,0L9,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M19,0L19,108" <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:pathData="M29,0L29,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M39,0L39,108" <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:pathData="M49,0L49,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M59,0L59,108" <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:pathData="M69,0L69,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M79,0L79,108" <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:pathData="M89,0L89,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M99,0L99,108" <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:pathData="M0,9L108,9" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M0,19L108,19" <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:pathData="M0,29L108,29" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector> </vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<gradient xmlns:android="http://schemas.android.com/apk/res/android"
android:startColor="#87CEEB"
android:endColor="#1E90FF"
android:angle="45"
android:type="linear" />

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/background_gradient">
<!-- TOOLBAR + TOMBOL BACK -->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbarChat"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@color/button_color"
app:title="Global Chat"
app:titleTextColor="@android:color/white"
app:navigationIcon="@android:drawable/ic_media_previous" />
<!-- RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="8dp"
android:scrollbars="vertical"
android:paddingBottom="8dp"
android:clipToPadding="false"
/>
<!-- Input -->
<EditText
android:id="@+id/etMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Type a message"
android:inputType="text"
android:padding="10dp"
android:layout_marginTop="8dp"
android:background="@android:color/white" />
<!-- Send -->
<Button
android:id="@+id/btnSend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send"
android:layout_marginTop="12dp"
android:layout_marginBottom="16dp"
android:textColor="@android:color/white"
android:background="@color/button_color" />
</LinearLayout>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:gravity="center"
android:background="@drawable/background_gradient">
<!-- Username Input Field -->
<EditText
android:id="@+id/etUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter username"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:background="@android:color/white"
android:padding="12dp" />
<!-- Login Button -->
<Button
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Login"
android:layout_marginTop="20dp" />
</LinearLayout>

View File

@ -1,198 +1,213 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout 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"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="16dp"
android:background="@drawable/background_gradient"> android:background="@drawable/background_gradient">
<LinearLayout <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:orientation="vertical"> android:padding="16dp">
<!-- Header Section --> <LinearLayout
<TextView android:id="@+id/mainLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/app_name" android:orientation="vertical"
android:textSize="32sp" android:background="@color/solid_background_color">
android:textStyle="bold"
android:textColor="@color/white"
android:gravity="center"
android:layout_marginBottom="32dp" />
<!-- Search Section --> <!-- Header -->
<com.google.android.material.card.MaterialCardView <androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="16dp"
app:cardElevation="8dp"
app:cardBackgroundColor="@color/card_background">
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:layout_marginBottom="32dp"
android:padding="16dp"> app:cardCornerRadius="16dp"
app:cardElevation="8dp"
app:cardBackgroundColor="@color/welcome_card_background">
<EditText <TextView
android:id="@+id/etSearch" android:id="@+id/tvWelcomeMessage"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Enter city name"
android:textColor="@color/white"
android:textColorHint="@color/hint_color"
android:background="@android:color/transparent"
android:padding="12dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnSearch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Search" android:padding="16dp"
android:text="Welcome!"
android:textColor="@color/white" android:textColor="@color/white"
app:icon="@drawable/ic_search" android:textSize="24sp"
app:cornerRadius="12dp" android:textStyle="bold" />
android:backgroundTint="@color/button_color" /> </androidx.cardview.widget.CardView>
</LinearLayout> <!-- Search -->
</com.google.android.material.card.MaterialCardView> <com.google.android.material.card.MaterialCardView
<!-- Loading Indicator -->
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
<!-- Error Message -->
<TextView
android:id="@+id/tvError"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/error_color"
android:gravity="center"
android:visibility="gone"
android:layout_marginBottom="16dp" />
<!-- Weather Data Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/weatherCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:cardCornerRadius="24dp"
app:cardElevation="12dp"
app:cardBackgroundColor="@color/weather_card_background">
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:layout_marginBottom="24dp"
android:padding="24dp"> app:cardCornerRadius="16dp"
app:cardElevation="8dp"
app:cardBackgroundColor="@color/card_background">
<!-- Location --> <LinearLayout
<TextView
android:id="@+id/tvLocation"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Location" android:orientation="horizontal"
android:textSize="24sp" android:padding="16dp">
android:textStyle="bold"
android:textColor="@color/white"
android:gravity="center"
android:layout_marginBottom="8dp" />
<!-- Temperature --> <EditText
<TextView android:id="@+id/etSearch"
android:id="@+id/tvTemperature" android:layout_width="0dp"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:layout_weight="1"
android:text="--°C" android:hint="Enter city name"
android:textSize="48sp" android:textColor="@color/white"
android:textStyle="bold" android:textColorHint="@color/hint_color"
android:textColor="@color/white" android:background="@android:color/transparent" />
android:gravity="center"
android:layout_marginBottom="16dp" />
<!-- Weather Condition --> <com.google.android.material.button.MaterialButton
<TextView android:id="@+id/btnSearch"
android:id="@+id/tvCondition"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Condition"
android:textSize="18sp"
android:textColor="@color/white"
android:gravity="center"
android:layout_marginBottom="24dp" />
<!-- Weather Details Grid -->
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="2"
android:rowCount="2">
<!-- Feels Like -->
<TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Feels Like:" android:text="Search"
android:textColor="@color/label_color" android:textColor="@color/white"
android:textSize="14sp" /> app:icon="@drawable/ic_search"
android:backgroundTint="@color/button_color" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Progress -->
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
<!-- Error -->
<TextView
android:id="@+id/tvError"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/error_color"
android:gravity="center"
android:visibility="gone"
android:layout_marginBottom="16dp" />
<!-- Weather Data Card (ID WAJIB sama seperti di MainActivity.kt) -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/weatherCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:cardCornerRadius="24dp"
app:cardElevation="12dp"
app:cardBackgroundColor="@color/weather_card_background">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView <TextView
android:id="@+id/tvFeelsLike" android:id="@+id/tvLocation"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Location"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/white"
android:gravity="center"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/tvTemperature"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="--°C" android:text="--°C"
android:textSize="48sp"
android:textStyle="bold"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="14sp" android:gravity="center"
android:layout_gravity="end" /> android:layout_marginBottom="16dp" />
<!-- Humidity -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Humidity:"
android:textColor="@color/label_color"
android:textSize="14sp" />
<TextView <TextView
android:id="@+id/tvHumidity" android:id="@+id/tvCondition"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="--%" android:text="Condition"
android:textSize="18sp"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="14sp" android:gravity="center"
android:layout_gravity="end" /> android:layout_marginBottom="24dp" />
<!-- Wind Speed --> <GridLayout
<TextView android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Wind:" android:columnCount="2">
android:textColor="@color/label_color"
android:textSize="14sp" />
<TextView <TextView
android:id="@+id/tvWind" android:layout_width="wrap_content"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:text="Feels Like:"
android:text="-- km/h" android:textColor="@color/label_color"
android:textColor="@color/white" android:textSize="14sp" />
android:textSize="14sp"
android:layout_gravity="end" />
</GridLayout> <TextView
android:id="@+id/tvFeelsLike"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="--°C"
android:textColor="@color/white"
android:textSize="14sp"
android:layout_gravity="end" />
</LinearLayout> <TextView
</com.google.android.material.card.MaterialCardView> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Humidity:"
android:textColor="@color/label_color"
android:textSize="14sp" />
</LinearLayout> <TextView
</ScrollView> android:id="@+id/tvHumidity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="--%"
android:textColor="@color/white"
android:textSize="14sp"
android:layout_gravity="end" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wind:"
android:textColor="@color/label_color"
android:textSize="14sp" />
<TextView
android:id="@+id/tvWind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-- km/h"
android:textColor="@color/white"
android:textSize="14sp"
android:layout_gravity="end" />
</GridLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
<!-- FAB CHAT GLOBAL -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabChat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="20dp"
android:contentDescription="Chat Global"
app:tint="@android:color/white"
app:backgroundTint="@color/button_color" />
</FrameLayout>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" /> <background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground" /> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon> </adaptive-icon>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" /> <background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground" /> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon> </adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -8,11 +8,34 @@
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<!-- Custom colors for our weather app --> <!-- Custom colors for weather app (Updated - No Transparent White) -->
<color name="button_color">#2196F3</color> <color name="button_color">#2196F3</color>
<color name="error_color">#FF5252</color> <color name="error_color">#FF5252</color>
<color name="hint_color">#B3FFFFFF</color>
<color name="label_color">#CCFFFFFF</color> <!-- CHANGED: Ganti dari transparan putih ke warna solid -->
<color name="card_background">#4DFFFFFF</color> <color name="hint_color">#78909C</color> <!-- Blue Grey 400 - untuk hint text -->
<color name="weather_card_background">#803496DB</color> <color name="label_color">#ECEFF1</color> <!-- Blue Grey 50 - untuk label -->
<color name="card_background">#37474F</color> <!-- Blue Grey 800 - untuk search card -->
<color name="weather_card_background">#546E7A</color> <!-- Blue Grey 600 - untuk weather card -->
<color name="blogin">#2196F3</color>
<color name="gray">#808080</color>
<color name="welcome_card_background">#1E90FF</color>
<!-- Weather condition colors -->
<color name="sunny">#FFEB3B</color> <!-- Yellow for sunny -->
<color name="rainy">#1976D2</color> <!-- Blue for rainy -->
<color name="cloudy">#90A4AE</color> <!-- Gray for cloudy -->
<color name="snowy">#FFFFFF</color> <!-- White for snowy -->
<color name="default_weather">#00BCD4</color>
<!-- Background colors for weather conditions -->
<color name="sunny_background">#FFFAE3</color> <!-- Light Yellow -->
<color name="rainy_background">#A7C7E7</color> <!-- Light Blue -->
<color name="cloudy_background">#D3D3D3</color> <!-- Light Gray -->
<color name="snowy_background">#F0F8FF</color> <!-- Alice Blue -->
<color name="default_weather_background">#E0E0E0</color> <!-- Very Light Gray -->
<color name="solid_background_color">#ADD8E6</color>
</resources> </resources>

View File

@ -1,5 +1,12 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // build.gradle.kts (Proyek Level)
plugins { buildscript {
alias(libs.plugins.android.application) apply false repositories {
alias(libs.plugins.kotlin.android) apply false google()
mavenCentral()
}
dependencies {
// Tambahkan plugin Google Services
classpath("com.google.gms:google-services:4.3.15")
}
} }