1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-20 08:39:08 -05:00

Add creators list (#636)

This commit is contained in:
Dominik Korsa 2020-01-22 10:59:13 +01:00 committed by Rafał Borcz
parent ad3bb3a522
commit 4640d114f6
18 changed files with 370 additions and 0 deletions

View File

@ -176,6 +176,8 @@ dependencies {
implementation "com.mikepenz:aboutlibraries-core:7.1.0" implementation "com.mikepenz:aboutlibraries-core:7.1.0"
implementation 'com.wdullaer:materialdatetimepicker:4.2.3' implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
implementation("io.coil-kt:coil:0.9.2")
playImplementation "com.google.firebase:firebase-core:17.2.2" playImplementation "com.google.firebase:firebase-core:17.2.2"
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1" playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"

View File

@ -0,0 +1,34 @@
[
{
"displayName": "Mikołaj Pich",
"githubUsername": "mklkj"
},
{
"displayName": "Rafał Borcz",
"githubUsername": "Faierbel"
},
{
"displayName": "Dominik Korsa",
"githubUsername": "dominik-korsa"
},
{
"displayName": "Kacper Ziubryniewicz",
"githubUsername": "kapi2289"
},
{
"displayName": "doteq",
"githubUsername": "doteq"
},
{
"displayName": "Pavuloff",
"githubUsername": "pavuloff"
},
{
"displayName": "Piotr Romanowski",
"githubUsername": "v0idzz"
},
{
"displayName": "Dinolek",
"githubUsername": "Dinolek"
}
]

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.data
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.AssetManager
import android.content.res.Resources import android.content.res.Resources
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
@ -58,6 +59,10 @@ internal class RepositoryModule {
@Provides @Provides
fun provideResources(context: Context): Resources = context.resources fun provideResources(context: Context): Resources = context.resources
@Singleton
@Provides
fun provideAssets(context: Context): AssetManager = context.assets
@Singleton @Singleton
@Provides @Provides
fun provideSharedPref(context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) fun provideSharedPref(context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)

View File

@ -0,0 +1,3 @@
package io.github.wulkanowy.data.pojos
class AppCreator(val displayName: String, val githubUsername: String)

View File

@ -0,0 +1,20 @@
package io.github.wulkanowy.data.repositories.appcreator
import android.content.res.AssetManager
import com.google.gson.Gson
import io.github.wulkanowy.data.pojos.AppCreator
import io.reactivex.Single
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class AppCreatorRepository @Inject constructor(private val assets: AssetManager) {
fun getAppCreators(): Single<List<AppCreator>> {
return Single.fromCallable<List<AppCreator>> {
Gson().fromJson(
assets.open("creators.json").bufferedReader().use { it.readText() },
Array<AppCreator>::class.java
).toList()
}
}
}

View File

@ -16,6 +16,7 @@ import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.about.creator.CreatorFragment
import io.github.wulkanowy.ui.modules.about.license.LicenseFragment import io.github.wulkanowy.ui.modules.about.license.LicenseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
@ -42,6 +43,11 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
Triple(getString(R.string.about_version), "${appInfo.versionName} (${appInfo.versionCode})", getCompatDrawable(R.drawable.ic_all_about)) Triple(getString(R.string.about_version), "${appInfo.versionName} (${appInfo.versionCode})", getCompatDrawable(R.drawable.ic_all_about))
} }
override val creatorsRes: Triple<String, String, Drawable?>?
get() = context?.run {
Triple(getString(R.string.about_creator), getString(R.string.about_creator_summary), getCompatDrawable(R.drawable.ic_about_creator))
}
override val feedbackRes: Triple<String, String, Drawable?>? override val feedbackRes: Triple<String, String, Drawable?>?
get() = context?.run { get() = context?.run {
Triple(getString(R.string.about_feedback), getString(R.string.about_feedback_summary), getCompatDrawable(R.drawable.ic_about_feedback)) Triple(getString(R.string.about_feedback), getString(R.string.about_feedback_summary), getCompatDrawable(R.drawable.ic_about_feedback))
@ -143,6 +149,10 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
(activity as? MainActivity)?.pushView(LicenseFragment.newInstance()) (activity as? MainActivity)?.pushView(LicenseFragment.newInstance())
} }
override fun openCreators() {
(activity as? MainActivity)?.pushView(CreatorFragment.newInstance())
}
override fun openPrivacyPolicy() { override fun openPrivacyPolicy() {
context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage) context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage)
} }

View File

@ -52,6 +52,11 @@ class AboutPresenter @Inject constructor(
openLicenses() openLicenses()
analytics.logEvent("about_open", "name" to "licenses") analytics.logEvent("about_open", "name" to "licenses")
} }
creatorsRes?.first -> {
Timber.i("Opening creators view")
openCreators()
analytics.logEvent("about_open", "name" to "creators")
}
privacyRes?.first -> { privacyRes?.first -> {
Timber.i("Opening privacy page ") Timber.i("Opening privacy page ")
openPrivacyPolicy() openPrivacyPolicy()
@ -65,6 +70,7 @@ class AboutPresenter @Inject constructor(
view?.run { view?.run {
updateData(AboutScrollableHeader(), listOfNotNull( updateData(AboutScrollableHeader(), listOfNotNull(
versionRes?.let { (title, summary, image) -> AboutItem(title, summary, image) }, versionRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
creatorsRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
feedbackRes?.let { (title, summary, image) -> AboutItem(title, summary, image) }, feedbackRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
faqRes?.let { (title, summary, image) -> AboutItem(title, summary, image) }, faqRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
discordRes?.let { (title, summary, image) -> AboutItem(title, summary, image) }, discordRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },

View File

@ -7,6 +7,8 @@ interface AboutView : BaseView {
val versionRes: Triple<String, String, Drawable?>? val versionRes: Triple<String, String, Drawable?>?
val creatorsRes: Triple<String, String, Drawable?>?
val feedbackRes: Triple<String, String, Drawable?>? val feedbackRes: Triple<String, String, Drawable?>?
val faqRes: Triple<String, String, Drawable?>? val faqRes: Triple<String, String, Drawable?>?
@ -33,5 +35,7 @@ interface AboutView : BaseView {
fun openLicenses() fun openLicenses()
fun openCreators()
fun openPrivacyPolicy() fun openPrivacyPolicy()
} }

View File

@ -0,0 +1,76 @@
package io.github.wulkanowy.ui.modules.about.creator
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_creator.*
import javax.inject.Inject
class CreatorFragment : BaseFragment(), CreatorView, MainView.TitledView {
@Inject
lateinit var presenter: CreatorPresenter
@Inject
lateinit var creatorsAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
override val titleStringId get() = R.string.creators_title
companion object {
fun newInstance() = CreatorFragment()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_creator, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
presenter.onAttachView(this)
}
override fun initView() {
with(creatorRecycler) {
layoutManager = SmoothScrollLinearLayoutManager(context)
adapter = creatorsAdapter
addItemDecoration(FlexibleItemDecoration(context)
.withDefaultDivider()
.withDrawDividerOnLastItem(false))
}
creatorsAdapter.setOnItemClickListener(presenter::onItemSelected)
creatorSeeMore.setOnClickListener { presenter.onSeeMoreClick() }
}
override fun updateData(data: List<CreatorItem>) {
creatorsAdapter.updateDataSet(data)
}
override fun openUserGithubPage(username: String) {
context?.openInternetBrowser("https://github.com/${username}", ::showMessage)
}
override fun openGithubContributorsPage() {
context?.openInternetBrowser("https://github.com/wulkanowy/wulkanowy/graphs/contributors", ::showMessage)
}
override fun showProgress(show: Boolean) {
creatorProgress.visibility = if (show) VISIBLE else GONE
}
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
}
}

View File

@ -0,0 +1,50 @@
package io.github.wulkanowy.ui.modules.about.creator
import android.view.View
import coil.api.load
import coil.transform.RoundedCornersTransformation
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import io.github.wulkanowy.R
import io.github.wulkanowy.data.pojos.AppCreator
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.item_creator.*
class CreatorItem(val creator: AppCreator) : AbstractFlexibleItem<CreatorItem.ViewHolder>() {
override fun getLayoutRes() = R.layout.item_creator
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>) = ViewHolder(view, adapter)
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder, position: Int, payloads: MutableList<Any>) {
with(holder) {
creatorItemName.text = creator.displayName
creatorItemAvatar.load("https://github.com/${creator.githubUsername}.png") {
transformations(RoundedCornersTransformation(8f))
crossfade(true)
}
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as CreatorItem
if (creator != other.creator) return false
return true
}
override fun hashCode() = creator.hashCode()
class ViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>) : FlexibleViewHolder(view, adapter),
LayoutContainer {
override val containerView: View? get() = contentView
}
}

View File

@ -0,0 +1,43 @@
package io.github.wulkanowy.ui.modules.about.creator
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.pojos.AppCreator
import io.github.wulkanowy.data.repositories.appcreator.AppCreatorRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.SchedulersProvider
import io.reactivex.Single
import javax.inject.Inject
class CreatorPresenter @Inject constructor(
schedulers: SchedulersProvider,
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val appCreatorRepository: AppCreatorRepository
) : BasePresenter<CreatorView>(errorHandler, studentRepository, schedulers) {
override fun onAttachView(view: CreatorView) {
super.onAttachView(view)
view.initView()
loadData()
}
fun onItemSelected(item: AbstractFlexibleItem<*>) {
if (item !is CreatorItem) return
view?.openUserGithubPage(item.creator.githubUsername)
}
fun onSeeMoreClick() {
view?.openGithubContributorsPage()
}
private fun loadData() {
disposable.add(appCreatorRepository.getAppCreators()
.map { it.map { creator -> CreatorItem(creator) } }
.subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread)
.doFinally { view?.showProgress(false) }
.subscribe({ view?.run { updateData(it) } }, { errorHandler.dispatch(it) }))
}
}

View File

@ -0,0 +1,16 @@
package io.github.wulkanowy.ui.modules.about.creator
import io.github.wulkanowy.ui.base.BaseView
interface CreatorView : BaseView {
fun initView()
fun updateData(data: List<CreatorItem>)
fun openUserGithubPage(username: String)
fun openGithubContributorsPage()
fun showProgress(show: Boolean)
}

View File

@ -8,6 +8,7 @@ import dagger.android.ContributesAndroidInjector
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.di.scopes.PerFragment import io.github.wulkanowy.di.scopes.PerFragment
import io.github.wulkanowy.ui.modules.about.AboutFragment import io.github.wulkanowy.ui.modules.about.AboutFragment
import io.github.wulkanowy.ui.modules.about.creator.CreatorFragment
import io.github.wulkanowy.ui.modules.about.license.LicenseFragment import io.github.wulkanowy.ui.modules.about.license.LicenseFragment
import io.github.wulkanowy.ui.modules.about.license.LicenseModule import io.github.wulkanowy.ui.modules.about.license.LicenseModule
import io.github.wulkanowy.ui.modules.account.AccountDialog import io.github.wulkanowy.ui.modules.account.AccountDialog
@ -121,6 +122,10 @@ abstract class MainModule {
@ContributesAndroidInjector(modules = [LicenseModule::class]) @ContributesAndroidInjector(modules = [LicenseModule::class])
abstract fun bindLicenseFragment(): LicenseFragment abstract fun bindLicenseFragment(): LicenseFragment
@PerFragment
@ContributesAndroidInjector()
abstract fun bindCreatorsFragment(): CreatorFragment
@PerFragment @PerFragment
@ContributesAndroidInjector(modules = [SchoolAndTeachersModule::class]) @ContributesAndroidInjector(modules = [SchoolAndTeachersModule::class])
abstract fun bindSchoolAndTeachersFragment(): SchoolAndTeachersFragment abstract fun bindSchoolAndTeachersFragment(): SchoolAndTeachersFragment

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFF"
android:pathData="M9,13.75c-2.34,0 -7,1.17 -7,3.5L2,19h14v-1.75c0,-2.33 -4.66,-3.5 -7,-3.5zM4.34,17c0.84,-0.58 2.87,-1.25 4.66,-1.25s3.82,0.67 4.66,1.25L4.34,17zM9,12c1.93,0 3.5,-1.57 3.5,-3.5S10.93,5 9,5 5.5,6.57 5.5,8.5 7.07,12 9,12zM9,7c0.83,0 1.5,0.67 1.5,1.5S9.83,10 9,10s-1.5,-0.67 -1.5,-1.5S8.17,7 9,7zM16.04,13.81c1.16,0.84 1.96,1.96 1.96,3.44L18,19h4v-1.75c0,-2.02 -3.5,-3.17 -5.96,-3.44zM15,12c1.93,0 3.5,-1.57 3.5,-3.5S16.93,5 15,5c-0.54,0 -1.04,0.13 -1.5,0.35 0.63,0.89 1,1.98 1,3.15s-0.37,2.26 -1,3.15c0.46,0.22 0.96,0.35 1.5,0.35z"/>
</vector>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/creatorProgress"
style="@style/Widget.MaterialProgressBar.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/creatorRecycler"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.google.android.material.button.MaterialButton
android:id="@+id/creatorSeeMore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="32dp"
android:layout_marginRight="32dp"
android:text="@string/creator_see_more" />
</LinearLayout>
</FrameLayout>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="56dp"
android:background="?selectableItemBackground"
android:orientation="vertical">
<ImageView
android:id="@+id/creatorItemAvatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:contentDescription="@string/creator_avatar_description"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/creatorItemName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:textSize="16sp"
tools:text="@tools:sample/lorem"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/creatorItemAvatar"
android:layout_toRightOf="@id/creatorItemAvatar"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp" />
</RelativeLayout>

View File

@ -12,6 +12,7 @@
<string name="settings_title">Ustawienia</string> <string name="settings_title">Ustawienia</string>
<string name="more_title">Więcej</string> <string name="more_title">Więcej</string>
<string name="about_title">O aplikacji</string> <string name="about_title">O aplikacji</string>
<string name="creators_title">Twórcy</string>
<string name="license_title">Licencje</string> <string name="license_title">Licencje</string>
<string name="message_title">Wiadomości</string> <string name="message_title">Wiadomości</string>
<string name="send_message_title">Nowa wiadomość</string> <string name="send_message_title">Nowa wiadomość</string>
@ -269,6 +270,8 @@
<!--About--> <!--About-->
<string name="about_version">Wersja aplikacji</string> <string name="about_version">Wersja aplikacji</string>
<string name="about_creator">Twórcy</string>
<string name="about_creator_summary">Lista programistów Wulkanowego</string>
<string name="about_feedback">Zgłoś błąd</string> <string name="about_feedback">Zgłoś błąd</string>
<string name="about_feedback_summary">Wyślij zgłoszenie o błędzie poprzez e-maila</string> <string name="about_feedback_summary">Wyślij zgłoszenie o błędzie poprzez e-maila</string>
<string name="about_faq">FAQ</string> <string name="about_faq">FAQ</string>
@ -287,6 +290,11 @@
<string name="license_dialog_title">Licencja</string> <string name="license_dialog_title">Licencja</string>
<!--Creators-->
<string name="creator_avatar_description">Awatar</string>
<string name="creator_see_more">Zobacz więcej na GitHub</string>
<!--Generic--> <!--Generic-->
<string name="all_content">Treść</string> <string name="all_content">Treść</string>
<string name="all_retry">Ponów</string> <string name="all_retry">Ponów</string>

View File

@ -12,6 +12,7 @@
<string name="settings_title">Settings</string> <string name="settings_title">Settings</string>
<string name="more_title">More</string> <string name="more_title">More</string>
<string name="about_title">About</string> <string name="about_title">About</string>
<string name="creators_title">Creators</string>
<string name="license_title">Licenses</string> <string name="license_title">Licenses</string>
<string name="message_title">Messages</string> <string name="message_title">Messages</string>
<string name="send_message_title">New message</string> <string name="send_message_title">New message</string>
@ -250,6 +251,8 @@
<!--About--> <!--About-->
<string name="about_version">App version</string> <string name="about_version">App version</string>
<string name="about_creator">Creators</string>
<string name="about_creator_summary">List of Wulkanowy developers</string>
<string name="about_feedback">Report a bug</string> <string name="about_feedback">Report a bug</string>
<string name="about_feedback_summary">Send a bug report via e-mail</string> <string name="about_feedback_summary">Send a bug report via e-mail</string>
<string name="about_faq">FAQ</string> <string name="about_faq">FAQ</string>
@ -268,6 +271,11 @@
<string name="license_dialog_title">License</string> <string name="license_dialog_title">License</string>
<!--Creators-->
<string name="creator_avatar_description">Avatar</string>
<string name="creator_see_more">See more on GitHub</string>
<!--Generic--> <!--Generic-->
<string name="all_content">Content</string> <string name="all_content">Content</string>
<string name="all_retry">Retry</string> <string name="all_retry">Retry</string>