add onboarding (login), change default theme to dark

closes #14
This commit is contained in:
Jannik 2021-01-16 00:16:47 +01:00
parent 3f45d769d2
commit 8a22554846
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
34 changed files with 514 additions and 67 deletions

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<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"
package="org.mosad.teapod"> package="org.mosad.teapod">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
@ -10,9 +11,9 @@
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme.Light"> android:theme="@style/AppTheme.Dark">
<activity <activity
android:name=".SplashActivity" android:name=".activity.SplashActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/SplashTheme" android:theme="@style/SplashTheme"
android:screenOrientation="portrait"> android:screenOrientation="portrait">
@ -22,20 +23,28 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".MainActivity" android:name=".activity.onboarding.OnboardingActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustPan">
</activity>
<activity
android:name=".activity.main.MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:screenOrientation="portrait"> android:screenOrientation="portrait">
</activity> </activity>
<activity <activity
android:name=".player.PlayerActivity" android:name="org.mosad.teapod.activity.player.PlayerActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|layoutDirection" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|layoutDirection"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="singleTask" android:launchMode="singleTask"
android:parentActivityName=".MainActivity" android:parentActivityName=".activity.main.MainActivity"
android:supportsPictureInPicture="true" android:supportsPictureInPicture="true"
android:taskAffinity=".player.PlayerActivity" android:taskAffinity=".player.PlayerActivity"
android:theme="@style/PlayerTheme" /> android:theme="@style/PlayerTheme"
tools:targetApi="n" />
</application> </application>
</manifest> </manifest>

View File

@ -1,8 +1,9 @@
package org.mosad.teapod package org.mosad.teapod.activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import org.mosad.teapod.activity.main.MainActivity
class SplashActivity : AppCompatActivity() { class SplashActivity : AppCompatActivity() {

View File

@ -20,7 +20,7 @@
* *
*/ */
package org.mosad.teapod package org.mosad.teapod.activity.main
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
@ -34,16 +34,18 @@ import com.afollestad.materialdialogs.callbacks.onDismiss
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import kotlinx.coroutines.joinAll import kotlinx.coroutines.joinAll
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.mosad.teapod.R
import org.mosad.teapod.databinding.ActivityMainBinding import org.mosad.teapod.databinding.ActivityMainBinding
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.player.PlayerActivity import org.mosad.teapod.activity.player.PlayerActivity
import org.mosad.teapod.preferences.EncryptedPreferences import org.mosad.teapod.preferences.EncryptedPreferences
import org.mosad.teapod.preferences.Preferences import org.mosad.teapod.preferences.Preferences
import org.mosad.teapod.ui.components.LoginDialog import org.mosad.teapod.ui.components.LoginDialog
import org.mosad.teapod.ui.fragments.AccountFragment import org.mosad.teapod.activity.main.fragments.AccountFragment
import org.mosad.teapod.ui.fragments.HomeFragment import org.mosad.teapod.activity.main.fragments.HomeFragment
import org.mosad.teapod.ui.fragments.LibraryFragment import org.mosad.teapod.activity.main.fragments.LibraryFragment
import org.mosad.teapod.ui.fragments.SearchFragment import org.mosad.teapod.activity.main.fragments.SearchFragment
import org.mosad.teapod.activity.onboarding.OnboardingActivity
import org.mosad.teapod.util.DataTypes import org.mosad.teapod.util.DataTypes
import org.mosad.teapod.util.StorageController import org.mosad.teapod.util.StorageController
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
@ -120,8 +122,8 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
private fun getThemeResource(): Int { private fun getThemeResource(): Int {
return when (Preferences.theme) { return when (Preferences.theme) {
DataTypes.Theme.DARK -> R.style.AppTheme_Dark DataTypes.Theme.LIGHT -> R.style.AppTheme_Light
else -> R.style.AppTheme_Light else -> R.style.AppTheme_Dark
} }
} }
@ -138,22 +140,23 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
EncryptedPreferences.readCredentials(this) EncryptedPreferences.readCredentials(this)
StorageController.load(this) StorageController.load(this)
try { // show onbaording
// make sure credentials are set, run's async if (EncryptedPreferences.password.isEmpty()) {
if (EncryptedPreferences.password.isEmpty()) { showOnboarding()
showLoginDialog(true) } else {
} else { try {
// try to login in, as most sites can only bee loaded once loged in if (!AoDParser.login()) {
if (!AoDParser.login()) showLoginDialog(false) showLoginDialog()
} }
} catch (ex: SocketTimeoutException) { } catch (ex: SocketTimeoutException) {
Log.w(javaClass.name, "Timeout during login!") Log.w(javaClass.name, "Timeout during login!")
// show waring dialog before finishing // show waring dialog before finishing
MaterialDialog(this).show { MaterialDialog(this).show {
title(R.string.dialog_timeout_head) title(R.string.dialog_timeout_head)
message(R.string.dialog_timeout_desc) message(R.string.dialog_timeout_desc)
onDismiss { exitAndRemoveTask() } onDismiss { exitAndRemoveTask() }
}
} }
} }
@ -164,12 +167,12 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
wasInitialized = true wasInitialized = true
} }
private fun showLoginDialog(firstTry: Boolean) { private fun showLoginDialog() {
LoginDialog(this, firstTry).positiveButton { LoginDialog(this, false).positiveButton {
EncryptedPreferences.saveCredentials(login, password, context) EncryptedPreferences.saveCredentials(login, password, context)
if (!AoDParser.login()) { if (!AoDParser.login()) {
showLoginDialog(false) showLoginDialog()
Log.w(javaClass.name, "Login failed, please try again.") Log.w(javaClass.name, "Login failed, please try again.")
} }
}.negativeButton { }.negativeButton {
@ -178,6 +181,14 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
}.show() }.show()
} }
/**
* start the onboarding activity and finish the main activity
*/
private fun showOnboarding() {
startActivity(Intent(this, OnboardingActivity::class.java))
finish()
}
/** /**
* Show a fragment on top of the current fragment. * Show a fragment on top of the current fragment.
* The current fragment is replaced and the new one is added * The current fragment is replaced and the new one is added

View File

@ -1,4 +1,4 @@
package org.mosad.teapod.ui.fragments package org.mosad.teapod.activity.main.fragments
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater

View File

@ -1,4 +1,4 @@
package org.mosad.teapod.ui.fragments package org.mosad.teapod.activity.main.fragments
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
@ -9,7 +9,7 @@ import androidx.fragment.app.Fragment
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItemsSingleChoice import com.afollestad.materialdialogs.list.listItemsSingleChoice
import org.mosad.teapod.BuildConfig import org.mosad.teapod.BuildConfig
import org.mosad.teapod.MainActivity import org.mosad.teapod.activity.main.MainActivity
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.databinding.FragmentAccountBinding import org.mosad.teapod.databinding.FragmentAccountBinding
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser

View File

@ -1,4 +1,4 @@
package org.mosad.teapod.ui.fragments package org.mosad.teapod.activity.main.fragments
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
@ -14,7 +14,7 @@ import com.bumptech.glide.request.transition.Transition
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.mosad.teapod.MainActivity import org.mosad.teapod.activity.main.MainActivity
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.databinding.FragmentHomeBinding import org.mosad.teapod.databinding.FragmentHomeBinding
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser

View File

@ -1,4 +1,4 @@
package org.mosad.teapod.ui.fragments package org.mosad.teapod.activity.main.fragments
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -9,7 +9,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.mosad.teapod.MainActivity import org.mosad.teapod.activity.main.MainActivity
import org.mosad.teapod.databinding.FragmentLibraryBinding import org.mosad.teapod.databinding.FragmentLibraryBinding
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.util.adapter.MediaItemAdapter import org.mosad.teapod.util.adapter.MediaItemAdapter

View File

@ -1,4 +1,4 @@
package org.mosad.teapod.ui.fragments package org.mosad.teapod.activity.main.fragments
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
@ -12,8 +12,8 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import jp.wasabeef.glide.transformations.BlurTransformation import jp.wasabeef.glide.transformations.BlurTransformation
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.mosad.teapod.MainActivity
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.activity.main.MainActivity
import org.mosad.teapod.databinding.FragmentMediaBinding import org.mosad.teapod.databinding.FragmentMediaBinding
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.util.* import org.mosad.teapod.util.*

View File

@ -1,4 +1,4 @@
package org.mosad.teapod.ui.fragments package org.mosad.teapod.activity.main.fragments
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -7,7 +7,7 @@ import android.view.ViewGroup
import android.widget.SearchView import android.widget.SearchView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.mosad.teapod.MainActivity import org.mosad.teapod.activity.main.MainActivity
import org.mosad.teapod.databinding.FragmentSearchBinding import org.mosad.teapod.databinding.FragmentSearchBinding
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.util.decoration.MediaItemDecoration import org.mosad.teapod.util.decoration.MediaItemDecoration

View File

@ -0,0 +1,54 @@
package org.mosad.teapod.activity.onboarding
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.coroutines.*
import org.mosad.teapod.R
import org.mosad.teapod.databinding.FragmentOnLoginBinding
import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.preferences.EncryptedPreferences
class OnLoginFragment: Fragment() {
private lateinit var binding: FragmentOnLoginBinding
private var loginJob: Job? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentOnLoginBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initActions()
}
private fun initActions() {
binding.buttonLogin.setOnClickListener {
// get login credentials from gui
val email = binding.editTextLogin.text.toString()
val password = binding.editTextPassword.text.toString()
EncryptedPreferences.saveCredentials(email, password, requireContext()) // save the credentials
binding.buttonLogin.isClickable = false
loginJob = GlobalScope.launch {
if (AoDParser.login()) {
// if login was successful, switch to main
if (activity is OnboardingActivity) {
(activity as OnboardingActivity).launchMainActivity()
}
} else {
withContext(Dispatchers.Main) {
binding.textLoginDesc.text = getString(R.string.on_login_failed)
binding.buttonLogin.isClickable = true
}
}
}
}
}
}

View File

@ -0,0 +1,31 @@
package org.mosad.teapod.activity.onboarding
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import org.mosad.teapod.databinding.FragmentOnWelcomeBinding
class OnWelcomeFragment: Fragment() {
private lateinit var binding: FragmentOnWelcomeBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentOnWelcomeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initActions()
}
private fun initActions() {
binding.buttonGetStarted.setOnClickListener {
if (activity is OnboardingActivity) {
(activity as OnboardingActivity).nextFragment()
}
}
}
}

View File

@ -0,0 +1,78 @@
package org.mosad.teapod.activity.onboarding
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayoutMediator
import org.mosad.teapod.activity.main.MainActivity
import org.mosad.teapod.databinding.ActivityOnboardingBinding
class OnboardingActivity : AppCompatActivity() {
private lateinit var binding: ActivityOnboardingBinding
private lateinit var pagerAdapter: FragmentStateAdapter
private val fragments = arrayOf(OnLoginFragment())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityOnboardingBinding.inflate(layoutInflater)
setContentView(binding.root)
pagerAdapter = ScreenSlidePagerAdapter(this)
binding.viewPager.adapter = pagerAdapter
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
}.attach()
// we don't use the skip button, instead we use the start button to skip the last fragment
binding.buttonSkip.visibility = View.GONE
// hide tab layout if only one tab is displayed
if (fragments.size <= 1) {
binding.tabLayout.visibility = View.GONE
}
}
override fun onBackPressed() {
if (binding.viewPager.currentItem == 0) {
super.onBackPressed()
} else {
binding.viewPager.currentItem = binding.viewPager.currentItem - 1
}
}
fun nextFragment() {
if (binding.viewPager.currentItem < fragments.size - 1) {
binding.viewPager.currentItem++
} else {
launchMainActivity()
}
}
fun btnSkipClick(@Suppress("UNUSED_PARAMETER")v: View) {
//launchMainActivity() // currently not used in Teapod
}
fun launchMainActivity() {
startActivity(Intent(this, MainActivity::class.java))
finish()
}
/**
* A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
* sequence.
*/
private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
override fun getItemCount(): Int = fragments.size
override fun createFragment(position: Int): Fragment = fragments[position]
}
}

View File

@ -1,4 +1,4 @@
package org.mosad.teapod.player package org.mosad.teapod.activity.player
import android.animation.Animator import android.animation.Animator
import android.animation.AnimatorListenerAdapter import android.animation.AnimatorListenerAdapter

View File

@ -1,4 +1,4 @@
package org.mosad.teapod.player package org.mosad.teapod.activity.player
import android.app.Application import android.app.Application
import android.net.Uri import android.net.Uri
@ -15,7 +15,6 @@ import kotlinx.coroutines.runBlocking
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.preferences.Preferences import org.mosad.teapod.preferences.Preferences
import org.mosad.teapod.ui.fragments.MediaFragment
import org.mosad.teapod.util.DataTypes import org.mosad.teapod.util.DataTypes
import org.mosad.teapod.util.Episode import org.mosad.teapod.util.Episode
import org.mosad.teapod.util.Media import org.mosad.teapod.util.Media

View File

@ -56,7 +56,7 @@ object AoDParser {
fun login(): Boolean = runBlocking { fun login(): Boolean = runBlocking {
withContext(Dispatchers.Default) { withContext(Dispatchers.IO) {
// get the authenticity token // get the authenticity token
val resAuth = Jsoup.connect(baseUrl + loginPath) val resAuth = Jsoup.connect(baseUrl + loginPath)
.header("User-Agent", userAgent) .header("User-Agent", userAgent)

View File

@ -11,7 +11,7 @@ object Preferences {
internal set internal set
var autoplay = true var autoplay = true
internal set internal set
var theme = DataTypes.Theme.LIGHT var theme = DataTypes.Theme.DARK
internal set internal set
private fun getSharedPref(context: Context): SharedPreferences { private fun getSharedPref(context: Context): SharedPreferences {
@ -62,8 +62,8 @@ object Preferences {
) )
theme = DataTypes.Theme.valueOf( theme = DataTypes.Theme.valueOf(
sharedPref.getString( sharedPref.getString(
context.getString(R.string.save_key_theme), DataTypes.Theme.LIGHT.toString() context.getString(R.string.save_key_theme), DataTypes.Theme.DARK.toString()
) ?: DataTypes.Theme.LIGHT.toString() ) ?: DataTypes.Theme.DARK.toString()
) )
} }

View File

@ -6,7 +6,7 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.LinearLayout import android.widget.LinearLayout
import org.mosad.teapod.databinding.PlayerEpisodesListBinding import org.mosad.teapod.databinding.PlayerEpisodesListBinding
import org.mosad.teapod.player.PlayerViewModel import org.mosad.teapod.activity.player.PlayerViewModel
import org.mosad.teapod.util.adapter.PlayerEpisodeItemAdapter import org.mosad.teapod.util.adapter.PlayerEpisodeItemAdapter
class EpisodesListPlayer @JvmOverloads constructor( class EpisodesListPlayer @JvmOverloads constructor(

View File

@ -13,7 +13,7 @@ import android.widget.TextView
import androidx.core.view.children import androidx.core.view.children
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.databinding.PlayerLanguageSettingsBinding import org.mosad.teapod.databinding.PlayerLanguageSettingsBinding
import org.mosad.teapod.player.PlayerViewModel import org.mosad.teapod.activity.player.PlayerViewModel
import java.util.* import java.util.*
class LanguageSettingsPlayer @JvmOverloads constructor( class LanguageSettingsPlayer @JvmOverloads constructor(

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="?iconColor"/>
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="@color/colorAccent" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/dot_selected"
android:state_selected="true"/>
<item android:drawable="@drawable/dot_default"/>
</selector>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.viewpager2.widget.ViewPager2>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom"
android:layout_marginBottom="0dp"
android:background="@android:color/transparent"
app:tabBackground="@drawable/dot_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPaddingStart="6dp"
app:tabPaddingEnd="6dp"/>
<Button
android:id="@+id/button_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:background="@null"
android:onClick="btnNextClick"
android:text="@string/next"
android:visibility="gone" />
<Button
android:id="@+id/button_skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:background="@null"
android:onClick="btnSkipClick"
android:text="@string/skip"
tools:visibility="gone" />
</RelativeLayout>

View File

@ -7,7 +7,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#000000" android:background="#000000"
android:keepScreenOn="true" android:keepScreenOn="true"
tools:context=".player.PlayerActivity"> tools:context=".activity.player.PlayerActivity">
<com.google.android.exoplayer2.ui.StyledPlayerView <com.google.android.exoplayer2.ui.StyledPlayerView
android:id="@+id/video_view" android:id="@+id/video_view"

View File

@ -4,7 +4,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?themePrimary" android:background="?themePrimary"
tools:context=".ui.fragments.AboutFragment"> tools:context=".activity.main.fragments.AboutFragment">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?themePrimary" android:background="?themePrimary"
tools:context=".ui.fragments.AccountFragment"> tools:context=".activity.main.fragments.AccountFragment">
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -6,7 +6,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?themePrimary" android:background="?themePrimary"
tools:context=".ui.fragments.HomeFragment"> tools:context=".activity.main.fragments.HomeFragment">
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?themePrimary" android:background="?themePrimary"
tools:context=".ui.fragments.LibraryFragment"> tools:context=".activity.main.fragments.LibraryFragment">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_media_library" android:id="@+id/recycler_media_library"

View File

@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?themePrimary" android:background="?themePrimary"
tools:context=".ui.fragments.MediaFragment"> tools:context=".activity.main.fragments.MediaFragment">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -134,9 +134,9 @@
android:id="@+id/image_my_list_action" android:id="@+id/image_my_list_action"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="48dp" android:layout_height="48dp"
android:contentDescription="@string/my_list"
android:src="@drawable/ic_baseline_add_24" android:src="@drawable/ic_baseline_add_24"
app:tint="?buttonBackground" app:tint="?buttonBackground" />
android:contentDescription="@string/my_list" />
<TextView <TextView
android:id="@+id/text_my_list_action" android:id="@+id/text_my_list_action"

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="?themePrimary">
<ImageView
android:id="@+id/image_login"
android:layout_width="128dp"
android:layout_height="128dp"
android:contentDescription="@string/app_name"
android:scaleType="fitCenter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_launcher_foreground"
app:tint="?buttonBackground" />
<LinearLayout
android:id="@+id/linear_login"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image_login">
<TextView
android:id="@+id/text_login_heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/on_login_heading"
android:textAlignment="center"
android:textSize="26sp"
android:textStyle="bold" />
<TextView
android:id="@+id/text_login_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="7dp"
android:text="@string/on_login_desc"
android:textAlignment="center"
android:textSize="18sp" />
<EditText
android:id="@+id/edit_text_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="7dp"
android:ems="10"
android:hint="@string/login"
android:importantForAutofill="no"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/edit_text_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="7dp"
android:ems="10"
android:hint="@string/password"
android:importantForAutofill="no"
android:inputType="textPassword" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_login"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="7dp"
android:layout_marginTop="7dp"
android:layout_marginEnd="7dp"
android:text="@string/login"
android:textAllCaps="false"
android:textColor="#FFFFFFFF"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,74 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?themePrimary">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_logo"
android:layout_width="128dp"
android:layout_height="128dp"
android:contentDescription="@string/app_name"
android:scaleType="fitCenter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_launcher_foreground"
app:tint="?buttonBackground" />
<LinearLayout
android:id="@+id/linearLayout3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image_logo">
<TextView
android:id="@+id/text_app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textAlignment="center"
android:textSize="26sp"
android:textStyle="bold" />
<TextView
android:id="@+id/text_welcome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="7dp"
android:text="@string/on_welcome"
android:textAlignment="center"
android:textSize="18sp" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_get_started"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="40dp"
android:text="@string/on_get_started"
android:textAllCaps="false"
android:textColor="#FFFFFFFF"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View File

@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?themePrimary" android:background="?themePrimary"
tools:context=".ui.fragments.SearchFragment"> tools:context=".activity.main.fragments.SearchFragment">
<SearchView <SearchView
android:id="@+id/search_text" android:id="@+id/search_text"

View File

@ -7,25 +7,25 @@
<fragment <fragment
android:id="@+id/navigation_home" android:id="@+id/navigation_home"
android:name="org.mosad.teapod.ui.fragments.HomeFragment" android:name="org.mosad.teapod.activity.main.fragments.HomeFragment"
android:label="@string/title_home" android:label="@string/title_home"
tools:layout="@layout/fragment_home" /> tools:layout="@layout/fragment_home" />
<fragment <fragment
android:id="@+id/navigation_library" android:id="@+id/navigation_library"
android:name="org.mosad.teapod.ui.fragments.LibraryFragment" android:name="org.mosad.teapod.activity.main.fragments.LibraryFragment"
android:label="@string/title_library" android:label="@string/title_library"
tools:layout="@layout/fragment_library" /> tools:layout="@layout/fragment_library" />
<fragment <fragment
android:id="@+id/navigation_search" android:id="@+id/navigation_search"
android:name="org.mosad.teapod.ui.fragments.SearchFragment" android:name="org.mosad.teapod.activity.main.fragments.SearchFragment"
android:label="@string/title_search" android:label="@string/title_search"
tools:layout="@layout/fragment_search" /> tools:layout="@layout/fragment_search" />
<fragment <fragment
android:id="@+id/navigation_account" android:id="@+id/navigation_account"
android:name="org.mosad.teapod.ui.fragments.AccountFragment" android:name="org.mosad.teapod.activity.main.fragments.AccountFragment"
android:label="@string/title_account" android:label="@string/title_account"
tools:layout="@layout/fragment_account" /> tools:layout="@layout/fragment_account" />

View File

@ -56,6 +56,16 @@
<string name="episodes">Folgen</string> <string name="episodes">Folgen</string>
<string name="episode">Folge</string> <string name="episode">Folge</string>
<!-- Onboarding -->
<string name="skip">Überspringen</string>
<string name="next">Weiter</string>
<string name="start">Fertig</string>
<string name="on_welcome">Willkommen!\nTeapod ist eine inoffizielle App für AoD.</string>
<string name="on_get_started">Los geht\'s</string>
<string name="on_login_heading">Login</string>
<string name="on_login_desc">Um Teapod verwenden zu können musst du dich mit deinem AoD Account anmelden. Deine Login-Daten werden verschlüsselt auf deinem Gerät gespeichert.</string>
<string name="on_login_failed">Login nicht erfolgreich! Stelle sicher das deine Login-Daten korrekt sind und versuche es erneut.</string>
<!-- dialogs --> <!-- dialogs -->
<string name="save">speichern</string> <string name="save">speichern</string>
<string name="cancel">@android:string/cancel</string> <string name="cancel">@android:string/cancel</string>

View File

@ -72,6 +72,16 @@
<string name="episodes">Episodes</string> <string name="episodes">Episodes</string>
<string name="episode">Episode</string> <string name="episode">Episode</string>
<!-- Onboarding -->
<string name="skip">Skip</string>
<string name="next">Next</string>
<string name="start">Start</string>
<string name="on_welcome">Welcome!\nTeapod is an unofficial App for AoD.</string>
<string name="on_get_started">Get started</string>
<string name="on_login_heading">Login</string>
<string name="on_login_desc">To use Teapod you need to log in with your AoD account. Your Login-Data will be stored encrypted on your device.</string>
<string name="on_login_failed">Could not login! Make sure Username and Password are correct and try again.</string>
<!-- dialogs --> <!-- dialogs -->
<string name="save">save</string> <string name="save">save</string>
<string name="cancel">@android:string/cancel</string> <string name="cancel">@android:string/cancel</string>
@ -81,7 +91,7 @@
<!-- etc --> <!-- etc -->
<string name="login">Login</string> <string name="login">Login</string>
<string name="login_desc">You need to login before you can use Teapod. The Login-Data will be stored encrypted on your device.</string> <string name="login_desc">You need to login before you can use Teapod. The Login-Data will be stored encrypted on your device.</string>
<string name="login_failed_desc">Could not login. Please try again.</string> <string name="login_failed_desc"> Please try again.</string>
<string name="password">Password</string> <string name="password">Password</string>
<!-- save keys --> <!-- save keys -->