Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translate #3

Merged
merged 2 commits into from
Dec 2, 2020
Merged
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
/captures
.externalNativeBuild
.cxx

/spotify-app-remote/build/
/spotify-auth/build/
39 changes: 7 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,9 @@
# Автоматические проверки для Технопроектов Android
# Проект по курсу InfoMail

В этом репозитории собраны автоматические проверки для студентов технопарка. Правила по которым они сформированны следуют стандартам индустрии и стайлгайдам крупных компаний (Google, Oracle)
## Описание идеи:
Приложение предоставляет сервисы для прослушивания музыки из Spotify и прилагает к каждой песне ее текст в оригинале с возможностью перевода. Работа основывается на использовании API Spotify, Genius и переводчика IBM Watson.

## Как этим пользоваться?

1. Справа сверху есть кнопка `Use this template`. Необходимо клацнуть по ней.

2. После того как вы создатите свой проект, в первую очередь, необходимо удалить этот файл и написать такой же, но про себя. При оформлении используется максимально простой формат файлов Markdown. Вот пример как выглядел бы README.md для моего проекта:
```
# Companion App

Приложение для подбора людей на концерт. Вам нужно найти компаньона на любое мероприятие? Это лучшее приложение для этого!

## Команда авторов

- [Никита Куликов](https://github.com/LionZXY)
- [Олег Морозенков](https://github.com/reo7sp)
- [Михаил Волынов](https://github.com/StealthTech)
- [Юрий Голубев](https://github.com/Ansile)
```
Как это выглядит можно глянуть [тут](https://gist.github.com/LionZXY/a6c7439da96172ec68a09f225818b73a)

3. Отредактировать файл можно из интерфейса
4. Дальше - важно. Новые изменения нужно создавать в отдельной ветке. Подробнее о процессе GitHub Flow можно почитать [на хабре](https://habr.com/ru/post/346066/)
5. Перед стартом советую пройти курс по Git "Введение" вот [тут](https://learngitbranching.js.org/)

Итак, форкаем репозиторий, редактируем README.md и добавляем новый код через feature-ветки. Не делайте изменения прямо в `master`!

## Что в этом репозитории находится?

- [CI.md](./CI.md) - описание как пользоваться локально инструментами
- `.github` - папка со скриптами Github и ресурсами для CI (`.github/workflows/assets`)
- `.idea` - тут лежат стили для проекта в Idea
## Команда авторов:
- Игорь Семенов (https://github.com/XJIEBYUJEK)
- Константин Смирнов (https://github.com/Archrahkshi)
- Андрей Фомин (https://github.com/HSEc0der)
5 changes: 3 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ dependencies {
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

implementation("com.squareup.okhttp3:okhttp:4.9.0")
implementation "com.squareup.okhttp3:okhttp:4.9.0"
implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.4.1'

implementation('com.ibm.watson:ibm-watson:8.6.3')
implementation 'com.ibm.watson:ibm-watson:8.6.3'
}
9 changes: 6 additions & 3 deletions app/src/main/java/com/archrahkshi/spotifine/data/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const val ALBUM_FROM_PLAYLIST_DISTINCTION = 5
const val ALBUMS = "albums"
const val ARTIST_FROM_ME_DISTINCTION = 2
const val ARTISTS = "artists"
const val CLIENT_ID = "fbe0ec189f0247f99909e75530bac38e"
const val DURATION = "duration"
const val FROM_ARTIST = "from_artist"
const val FROM_ME = "from_me"
Expand All @@ -15,6 +14,10 @@ const val LIST_TYPE = "list_type"
const val NAME = "name"
const val ONE_DIGIT = 9
const val PLAYLISTS = "playlists"
const val REDIRECT_URI = "http://localhost:8888/callback/"
const val REQUEST_CODE = 1337
const val SPOTIFY_CLIENT_ID = "fbe0ec189f0247f99909e75530bac38e"
const val SPOTIFY_REDIRECT_URI = "http://localhost:8888/callback/"
const val SPOTIFY_REQUEST_CODE = 1337
const val URL = "url"
const val TRANSLATOR_API_KEY = "Nbo7_ne4t1F0JTjcmCS_06yGOuJNdEc7efawvtOHS9i_"
const val TRANSLATOR_URL = "https://api.eu-gb.language-translator.watson.cloud.ibm.com"
const val TRANSLATOR_VERSION = "2018-05-01"
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ class TracksAdapter(
textViewTrackDuration.text = track.duration.milliseconds.toComponents { HH, mm, ss, _ ->
var duration = ""
if (HH > 0) duration += "$HH:"
if (duration.isNotEmpty() && mm < ONE_DIGIT) duration += '0'
if (duration.isNotEmpty() && mm <= ONE_DIGIT) duration += '0'
duration += "$mm:"
if (duration.isNotEmpty() && ss < ONE_DIGIT) duration += '0'
if (duration.isNotEmpty() && ss <= ONE_DIGIT) duration += '0'
"$duration$ss"
}
layoutItemList.setOnClickListener { clickListener(track) }
Expand Down
153 changes: 114 additions & 39 deletions app/src/main/java/com/archrahkshi/spotifine/ui/LyricsFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,26 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.archrahkshi.spotifine.R
import com.archrahkshi.spotifine.data.LyricsAdapter
import com.archrahkshi.spotifine.data.TRANSLATOR_API_KEY
import com.archrahkshi.spotifine.data.TRANSLATOR_URL
import com.archrahkshi.spotifine.data.TRANSLATOR_VERSION
import com.ibm.cloud.sdk.core.security.IamAuthenticator
import com.ibm.watson.language_translator.v3.LanguageTranslator
import com.ibm.watson.language_translator.v3.model.TranslateOptions
import com.ibm.watson.language_translator.v3.util.Language.RUSSIAN
import kotlinx.android.synthetic.main.fragment_lyrics.buttonTranslate
import kotlinx.android.synthetic.main.fragment_lyrics.recyclerViewLyrics
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Locale
import kotlin.coroutines.CoroutineContext

class LyricsFragment(private var isLyricsTranslated: Boolean) : Fragment() {
class LyricsFragment(
private val isLyricsTranslated: Boolean,
override val coroutineContext: CoroutineContext = Dispatchers.Main.immediate
) : Fragment(), CoroutineScope {

override fun onCreateView(
inflater: LayoutInflater,
Expand All @@ -21,46 +37,105 @@ class LyricsFragment(private var isLyricsTranslated: Boolean) : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val lyricsOriginal = listOf(
"Hoort u mij toe",
"Als ik u verhaal",
"Van oude sagen",
"Van reuzentijd",
"",
"Vertel ons de sagen",
"Van oeroude machten",
"In 't Gelderse land",
"Wat weet u nog meer?",
)
val lyricsTranslated = listOf(
"Послушай меня",
"Если я скажу тебе",
"Из старых саг",
"Из гигантских времен",
"",
"Расскажи нам саги",
"Древних сил",
"В стране Гелдерланд",
"Что еще ты знаешь?",
)
val lyrics = if (isLyricsTranslated) lyricsTranslated else lyricsOriginal
launch {
val originalLyrics = getOriginalLyrics()
if (isLyricsTranslated) {
val (detectedLanguage, translatedLyrics) = getTranslatedLyrics(originalLyrics)
val appLocale = Locale(RUSSIAN)
buttonTranslate.text = getString(
R.string.detected_language,
Locale(detectedLanguage).getDisplayLanguage(appLocale),
appLocale.getDisplayLanguage(appLocale)
)
recyclerViewLyrics.adapter = LyricsAdapter(translatedLyrics.split('\n'))
} else {
buttonTranslate.text = getString(R.string.translate)
recyclerViewLyrics.adapter = LyricsAdapter(originalLyrics.split('\n'))
}

val detectedLanguage = "..." // TODO
val toRussian = "$detectedLanguage > ${resources.getString(R.string.russian)}"
buttonTranslate.text =
if (isLyricsTranslated)
toRussian
else
resources.getString(R.string.translate)

buttonTranslate.setOnClickListener {
isLyricsTranslated = !isLyricsTranslated
fragmentManager?.beginTransaction()?.replace(
R.id.frameLayoutPlayer,
LyricsFragment(isLyricsTranslated)
)?.commit()
buttonTranslate.setOnClickListener {
fragmentManager?.beginTransaction()?.replace(
R.id.frameLayoutPlayer,
LyricsFragment(!isLyricsTranslated)
)?.commit()
}
}
}

recyclerViewLyrics.adapter = LyricsAdapter(lyrics)
private suspend fun getOriginalLyrics() = withContext(Dispatchers.IO) {
"""
Flying over darkened skies the battle will call
Distant angels crying in the eye of the storm
And the world falls under the starlight shining from heavens below
Long years of pain and sorrow searching for more
Cry for the touch of angels never before
And the stars fall on the horizon onwards and up through the pain

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

Ride the wind and fight the demon steel shining bright
Standing together forever onwards flames burning strong
Hot wind in hell of pain and sorrow now and ever onwards
We stare into the dawn of a new world

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

[Pre-Chorus]
Cry out for the fallen heroes
Lost in time ago
In our minds they still belong
When the sands of time are gone

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

[Chorus]
Rise over shadow mountains blazing with power
Crossing valleys endless tears in unity we stand
Far and wide across the land the victory is ours
On towards the gates of reason
Fight for the truth and the freedom
Gloria

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

Searching through the memories to open the door
Living on the edge of life like never before
And the ground chants under the moonlight facing their fears all the same

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

Heavens fear now open wide and up for the the call
All in stark reality the angels will fall
And the world cries out for the silence lost in the voices unknown

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

Blinded by the force of evil cries into the night
Never before have they seen the darkness now they are all gone
Out from the shadows storming on the wings of revelations
Your soul will feel no mercy come the dawn

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

Hold on for the morning after
Never to let go
In the fire's burning strong
When the tides of time roll on

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

[Chorus]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

[Pre-Chorus]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[checkstyle] reported by reviewdog 🐶
Line has trailing spaces.

[Chorus]
""".trimIndent()
}

private suspend fun getTranslatedLyrics(
lyricsOriginal: String
) = withContext(Dispatchers.IO) {
val result = LanguageTranslator(
TRANSLATOR_VERSION,
IamAuthenticator(TRANSLATOR_API_KEY)
).apply {
serviceUrl = TRANSLATOR_URL
}.translate(
TranslateOptions.Builder()
// Line separators must be doubled for the lyrics to be translated line by line,
// not as a uniform text
.addText(lyricsOriginal.replace("\n", "\n\n"))
.target(RUSSIAN)
.build()
).execute().result
Pair(
result.detectedLanguage,
// Returning to the original line separators
result.translations.first().translation.replace("\n\n", "\n")
)
}
}
14 changes: 7 additions & 7 deletions app/src/main/java/com/archrahkshi/spotifine/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.archrahkshi.spotifine.R
import com.archrahkshi.spotifine.data.ACCESS_TOKEN
import com.archrahkshi.spotifine.data.CLIENT_ID
import com.archrahkshi.spotifine.data.REDIRECT_URI
import com.archrahkshi.spotifine.data.REQUEST_CODE
import com.archrahkshi.spotifine.data.SPOTIFY_CLIENT_ID
import com.archrahkshi.spotifine.data.SPOTIFY_REDIRECT_URI
import com.archrahkshi.spotifine.data.SPOTIFY_REQUEST_CODE
import com.spotify.sdk.android.auth.AuthorizationClient
import com.spotify.sdk.android.auth.AuthorizationRequest
import com.spotify.sdk.android.auth.AuthorizationResponse
Expand All @@ -21,11 +21,11 @@ class MainActivity : AppCompatActivity() {

AuthorizationClient.openLoginActivity(
this,
REQUEST_CODE,
SPOTIFY_REQUEST_CODE,
AuthorizationRequest.Builder(
CLIENT_ID,
SPOTIFY_CLIENT_ID,
AuthorizationResponse.Type.TOKEN,
REDIRECT_URI
SPOTIFY_REDIRECT_URI
).apply {
setScopes(arrayOf("streaming", "user-library-read", "user-follow-read"))
}.build()
Expand All @@ -35,7 +35,7 @@ class MainActivity : AppCompatActivity() {
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)

if (requestCode == REQUEST_CODE) {
if (requestCode == SPOTIFY_REQUEST_CODE) {
val response: AuthorizationResponse? =
AuthorizationClient.getResponse(resultCode, intent)
when (response?.type) {
Expand Down
18 changes: 8 additions & 10 deletions app/src/main/java/com/archrahkshi/spotifine/ui/PlayerActivity.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package com.archrahkshi.spotifine.ui

import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import androidx.appcompat.app.AppCompatActivity
import com.archrahkshi.spotifine.R
import com.archrahkshi.spotifine.data.CLIENT_ID
import com.archrahkshi.spotifine.data.DURATION
import com.archrahkshi.spotifine.data.ID
import com.archrahkshi.spotifine.data.REDIRECT_URI
import com.archrahkshi.spotifine.data.SPOTIFY_CLIENT_ID
import com.archrahkshi.spotifine.data.SPOTIFY_REDIRECT_URI
import com.spotify.android.appremote.api.ConnectionParams
import com.spotify.android.appremote.api.Connector
import com.spotify.android.appremote.api.SpotifyAppRemote
Expand All @@ -35,15 +34,14 @@ class PlayerActivity : AppCompatActivity() {
val duration = intent.getLongExtra(DURATION, 0)
Log.wtf("id", id?.toString())
Log.wtf("duration", duration.toString())
val connectionParams = ConnectionParams.Builder(CLIENT_ID)
.setRedirectUri(REDIRECT_URI)
val connectionParams = ConnectionParams.Builder(SPOTIFY_CLIENT_ID)
.setRedirectUri(SPOTIFY_REDIRECT_URI)
.showAuthView(true)
.build()
SpotifyAppRemote.connect(
this,
connectionParams,
object : Connector.ConnectionListener {
@SuppressLint("SetTextI18n")
override fun onConnected(spotifyAppRemote: SpotifyAppRemote) {
[email protected] = spotifyAppRemote
val appRemote = [email protected]!!
Expand All @@ -52,7 +50,7 @@ class PlayerActivity : AppCompatActivity() {
val seekBar = findViewById<SeekBar>(R.id.seekBar)
seekBar.max = duration.toInt()
var flag = 0
buttonPlay.text = "PLAY"
buttonPlay.text = getString(R.string.play)
seekBar.setOnSeekBarChangeListener(
object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
Expand Down Expand Up @@ -81,17 +79,17 @@ class PlayerActivity : AppCompatActivity() {
0 -> {
appRemote.playerApi.play("spotify:track:$id")
flag = 1
buttonPlay.text = "PAUSE"
buttonPlay.text = getString(R.string.pause)
}
1 -> {
appRemote.playerApi.pause()
flag = 2
buttonPlay.text = "PLAY"
buttonPlay.text = getString(R.string.play)
}
2 -> {
appRemote.playerApi.resume()
flag = 1
buttonPlay.text = "PAUSE"
buttonPlay.text = getString(R.string.pause)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class TracksFragment(
recyclerViewTracks.adapter = TracksAdapter(
createTrackLists(args?.getString(URL), args?.getString(ACCESS_TOKEN))
) {
Log.i("Track", it.toString())
Log.i("Track clicked", it.toString())
startActivity(
Intent(activity, PlayerActivity::class.java).apply {
putExtra(ID, it.id)
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/layout/fragment_library_lists.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
android:id="@+id/recyclerViewLists"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarThumbVertical="@android:color/white"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="20"
tools:listitem="@layout/item_library_list" />

</FrameLayout>
Loading