Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET"/>

<application
android:name="com.example.playlistmaker.App"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/java/com/example/playlistmaker/App.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.playlistmaker

import android.app.Application
import androidx.appcompat.app.AppCompatDelegate



class App : Application() {

var darkTheme = false

override fun onCreate() {
super.onCreate()
}

fun switchTheme(darkThemeEnabled: Boolean) {
darkTheme = darkThemeEnabled
AppCompatDelegate.setDefaultNightMode(
if (darkThemeEnabled) {
AppCompatDelegate.MODE_NIGHT_YES

} else {
AppCompatDelegate.MODE_NIGHT_NO
}
)
}

}
5 changes: 5 additions & 0 deletions app/src/main/java/com/example/playlistmaker/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import android.widget.Button

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {

val sharedPrefs = getSharedPreferences(PREFERENCE, MODE_PRIVATE)
(applicationContext as App).switchTheme(sharedPrefs.getBoolean(SWITCH_KEY, false))


super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

Expand Down
134 changes: 89 additions & 45 deletions app/src/main/java/com/example/playlistmaker/SearchActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.example.playlistmaker


import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
Expand Down Expand Up @@ -30,47 +29,68 @@ class SearchActivity : AppCompatActivity() {
private lateinit var tracksList: RecyclerView
private lateinit var linearLayoutNothingFound: LinearLayout
private lateinit var linearLayoutSomethingWentWrong: LinearLayout
private lateinit var searchHistory: SearchHistory
private lateinit var rvHistory: RecyclerView
private lateinit var historyLayout: LinearLayout
private lateinit var inputEditText: EditText
private val tracks = ArrayList<Track>()
private val adapter = TracksAdapter(tracks)
private val itunesBaseUrl = "https://itunes.apple.com"


private val retrofit = Retrofit.Builder()
.baseUrl(itunesBaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
private val iTunesAPISearchService = retrofit.create(ITunesAPI::class.java)
private val onTrackClickListener = { tracks: Track ->
searchHistory.addTrackToHistory(tracks)
}
val adapter = TracksAdapter(tracks, onTrackClickListener)

@SuppressLint("NotifyDataSetChanged")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search)
val retrofit = Retrofit.Builder()
.baseUrl(itunesBaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()

val iTunesAPISearchService = retrofit.create(ITunesAPI::class.java)

searchHistory = SearchHistory(this)

linearLayoutNothingFound = findViewById(R.id.nothingFound)
linearLayoutSomethingWentWrong = findViewById(R.id.somethingWentWrong)
tracksList = findViewById(R.id.rvTracks)
buttonRefresh = findViewById(R.id.buttonRefresh)
tracksList.adapter = adapter
historyLayout = findViewById(R.id.historyLayout)
rvHistory = findViewById(R.id.rvHistory)
rvHistory.adapter = adapter

val buttonBack = findViewById<ImageView>(R.id.arrow_back_light)
buttonBack.setOnClickListener {
Intent(this, MainActivity::class.java)
finish()
}

val inputEditText = findViewById<EditText>(R.id.search_input_text)
inputEditText = findViewById(R.id.search_input_text)
if (valueTextInput != "") {
inputEditText.setText(valueTextInput)
}

inputEditText.setOnFocusChangeListener { _, hasFocus ->
updateHistoryView()
historyLayout.visibility = if (hasFocus && inputEditText.text.isEmpty()) View.VISIBLE else View.GONE
}

val clearButton = findViewById<ImageView>(R.id.buttonClearInputText)
clearButton.setOnClickListener {
inputEditText.setText("")
inputEditText.hideKeyboard()
adapter.notifyDataSetChanged()
allViewsVisibleGone()
updateHistoryView()
adapter.notifyDataSetChanged()
}

findViewById<Button>(R.id.buttonHistoryRefresh).setOnClickListener {
searchHistory.clearHistory()
updateHistoryView()
inputEditText.setText("")
inputEditText.requestFocus()
showKeyboard()
}

val textWatcher = object : TextWatcher {
Expand All @@ -79,16 +99,25 @@ class SearchActivity : AppCompatActivity() {
}

override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
historyLayout.visibility = if (inputEditText.hasFocus() && s?.isEmpty() == true) View.VISIBLE else View.GONE
clearButton.visibility = clearButtonVisibility(s)
if (savedInstanceState != null) {
valueTextInput = savedInstanceState.getString(TEXT_INPUT, DEFAULT_TEXT_INPUT)
}
inputEditText.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
searchSong()
}
if (inputEditText.text.isNotEmpty()) {
(tracksList.adapter as TracksAdapter).updateData(tracks)
searchSong()
}
}
false
}
if (inputEditText.text.isEmpty()) {
allViewsVisibleGone()
updateHistoryView()
}

buttonRefresh.setOnClickListener {
searchSong()
}
Expand All @@ -98,52 +127,63 @@ class SearchActivity : AppCompatActivity() {
// empty
}

fun searchSong(){
if (inputEditText.text.isNotEmpty()) {
iTunesAPISearchService.search(inputEditText.text.toString()).enqueue(object : Callback<TracksResponse> {
override fun onResponse(
call: Call<TracksResponse>,
response: Response<TracksResponse>) {
if (response.code() == 200) {
tracks.clear()
if (response.body()?.results?.isNotEmpty() == true) {
onlyTracksListVisible()
tracks.clear()
tracks.addAll(response.body()?.results!!)
adapter.notifyDataSetChanged()
}
if (tracks.isEmpty()) {
onlyLinearLayoutNothingFoundVisible()
}
} else {
onlyLinearLayoutSomethingWentWrongVisible()
}
}
override fun onFailure(call: Call<TracksResponse>, t: Throwable) {
onlyLinearLayoutSomethingWentWrongVisible()
}
})
}
}

}
inputEditText.addTextChangedListener(textWatcher)
}

fun searchSong(){
iTunesAPISearchService.search(inputEditText.text.toString()).enqueue(object : Callback<TracksResponse> {
@SuppressLint("NotifyDataSetChanged")
override fun onResponse(
call: Call<TracksResponse>,
response: Response<TracksResponse>) {
if (response.code() == 200) {
tracks.clear()
if (response.body()?.results?.isNotEmpty() == true) {
onlyTracksListVisible()
tracks.clear()
tracks.addAll(response.body()?.results!!)
adapter.notifyDataSetChanged()
}
if (tracks.isEmpty()) {
onlyLinearLayoutNothingFoundVisible()
}
} else {
onlyLinearLayoutSomethingWentWrongVisible()
}
}
override fun onFailure(call: Call<TracksResponse>, t: Throwable) {
onlyLinearLayoutSomethingWentWrongVisible()
}
})

}
private fun updateHistoryView() {
val history = searchHistory.getHistory()
if (history.isNotEmpty()) {
historyLayout.visibility = View.VISIBLE
} else {
historyLayout.visibility = View.GONE
}
(rvHistory.adapter as TracksAdapter).updateData(history)
}
private fun clearButtonVisibility(s: CharSequence?): Int {
return if (s.isNullOrEmpty()) {
View.GONE
} else {
View.VISIBLE
}
}

private fun View.hideKeyboard() {
val inputManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputManager.hideSoftInputFromWindow(windowToken, 0)
}

private fun showKeyboard() {
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(inputEditText, InputMethodManager.SHOW_IMPLICIT)
}
private var valueTextInput: String = DEFAULT_TEXT_INPUT

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString(TEXT_INPUT, valueTextInput)
Expand All @@ -160,20 +200,24 @@ class SearchActivity : AppCompatActivity() {
tracksList.visibility = View.GONE
linearLayoutSomethingWentWrong.visibility = View.GONE
linearLayoutNothingFound.visibility = View.GONE
historyLayout.visibility = View.GONE
}
private fun onlyTracksListVisible() {
tracksList.visibility = View.VISIBLE
linearLayoutSomethingWentWrong.visibility = View.GONE
linearLayoutNothingFound.visibility = View.GONE
historyLayout.visibility = View.GONE
}
private fun onlyLinearLayoutNothingFoundVisible() {
tracksList.visibility = View.GONE
linearLayoutSomethingWentWrong.visibility = View.GONE
linearLayoutNothingFound.visibility = View.VISIBLE
historyLayout.visibility = View.GONE
}
private fun onlyLinearLayoutSomethingWentWrongVisible() {
tracksList.visibility = View.GONE
linearLayoutSomethingWentWrong.visibility = View.VISIBLE
linearLayoutNothingFound.visibility = View.GONE
historyLayout.visibility = View.GONE
}
}
41 changes: 41 additions & 0 deletions app/src/main/java/com/example/playlistmaker/SearchHistory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.example.playlistmaker

import android.content.Context
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

class SearchHistory(private val context: Context) {

private val sharedPreferences = context.getSharedPreferences("SearchHistory", Context.MODE_PRIVATE)
private val historyKey = "search_history"
private val maxHistorySize = 10

fun addTrackToHistory(track: Track) {
val history = getHistory().toMutableList()
history.removeAll { it.trackName == track.trackName && it.artistName == track.artistName }
history.add(0, track)
if (history.size > maxHistorySize) {
history.removeAt(history.size - 1)
}
saveHistory(history)
}

fun getHistory(): List<Track> {
val historyJson = sharedPreferences.getString(historyKey, null)
return if (historyJson != null) {
val type = object : TypeToken<List<Track>>() {}.type
Gson().fromJson(historyJson, type)
} else {
emptyList()
}
}

private fun saveHistory(history: List<Track>) {
val historyJson = Gson().toJson(history)
sharedPreferences.edit().putString(historyKey, historyJson).apply()
}

fun clearHistory() {
sharedPreferences.edit().remove(historyKey).apply()
}
}
19 changes: 19 additions & 0 deletions app/src/main/java/com/example/playlistmaker/SettingsActivity.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
package com.example.playlistmaker

import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView
import android.widget.Switch

const val PREFERENCE = "preference"
const val SWITCH_KEY = "switch_key"

class SettingsActivity : AppCompatActivity() {
@SuppressLint("UseSwitchCompatOrMaterialCode")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)



val buttonBack = findViewById<ImageView>(R.id.arrow_back_light)
buttonBack.setOnClickListener {
Intent(this, MainActivity::class.java)
Expand Down Expand Up @@ -44,5 +53,15 @@ class SettingsActivity : AppCompatActivity() {
userAgreementIntent.data = Uri.parse(url)
startActivity(userAgreementIntent)
}
val themeSwitcher = findViewById<Switch>(R.id.themeSwitcher)

val sharedPrefs = getSharedPreferences(PREFERENCE, MODE_PRIVATE)
themeSwitcher.setOnCheckedChangeListener { _, isChecked ->
(applicationContext as App).switchTheme(isChecked)
sharedPrefs.edit()
.putBoolean(SWITCH_KEY, isChecked)
.apply()
}
themeSwitcher.isChecked = sharedPrefs.getBoolean(SWITCH_KEY, false)
}
}
Loading