├── .gitignore ├── .idea ├── assetWizardSettings.xml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── copyright │ └── horaciocome1.xml ├── dictionaries │ └── horaciocome1.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── navEditor.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── github │ │ └── horaciocome1 │ │ └── reaque │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── io │ │ │ └── github │ │ │ └── horaciocome1 │ │ │ └── reaque │ │ │ ├── data │ │ │ ├── Database.kt │ │ │ ├── bookmarks │ │ │ │ ├── BookmarksInterface.kt │ │ │ │ ├── BookmarksRepository.kt │ │ │ │ └── BookmarksService.kt │ │ │ ├── configurations │ │ │ │ ├── ConfigurationsInterface.kt │ │ │ │ ├── ConfigurationsRepository.kt │ │ │ │ └── ConfigurationsService.kt │ │ │ ├── feed │ │ │ │ ├── FeedInterface.kt │ │ │ │ ├── FeedRepository.kt │ │ │ │ └── FeedService.kt │ │ │ ├── posts │ │ │ │ ├── Post.kt │ │ │ │ ├── PostsInterface.kt │ │ │ │ ├── PostsRepository.kt │ │ │ │ └── PostsService.kt │ │ │ ├── ratings │ │ │ │ ├── RatingsInterface.kt │ │ │ │ ├── RatingsRepository.kt │ │ │ │ └── RatingsService.kt │ │ │ ├── readings │ │ │ │ ├── ReadingsInterface.kt │ │ │ │ ├── ReadingsRepository.kt │ │ │ │ └── ReadingsService.kt │ │ │ ├── shares │ │ │ │ ├── SharesInterface.kt │ │ │ │ ├── SharesRepository.kt │ │ │ │ └── SharesService.kt │ │ │ ├── storage │ │ │ │ ├── StorageRepository.kt │ │ │ │ └── StorageService.kt │ │ │ ├── subscriptions │ │ │ │ ├── SubscriptionsInterface.kt │ │ │ │ ├── SubscriptionsRepository.kt │ │ │ │ └── SubscriptionsService.kt │ │ │ ├── topics │ │ │ │ ├── Topic.kt │ │ │ │ ├── TopicsRepository.kt │ │ │ │ └── TopicsService.kt │ │ │ └── users │ │ │ │ ├── User.kt │ │ │ │ ├── UsersInterface.kt │ │ │ │ ├── UsersRepository.kt │ │ │ │ └── UsersService.kt │ │ │ ├── services │ │ │ └── MyFirebaseMessagingService.kt │ │ │ ├── ui │ │ │ ├── MainActivity.kt │ │ │ ├── explore │ │ │ │ ├── ExploreFragment.kt │ │ │ │ ├── ExploreViewModel.kt │ │ │ │ ├── ExploreViewModelFactory.kt │ │ │ │ └── TopicsAdapter.kt │ │ │ ├── feed │ │ │ │ ├── FeedFragment.kt │ │ │ │ ├── FeedViewModel.kt │ │ │ │ └── FeedViewModelFactory.kt │ │ │ ├── more │ │ │ │ ├── MoreFragment.kt │ │ │ │ ├── MoreViewModel.kt │ │ │ │ └── MoreViewModelFactory.kt │ │ │ ├── posts │ │ │ │ ├── PostsAdapter.kt │ │ │ │ ├── PostsFragment.kt │ │ │ │ ├── PostsViewModel.kt │ │ │ │ ├── PostsViewModelFactory.kt │ │ │ │ ├── create │ │ │ │ │ ├── CreatePostFragment.kt │ │ │ │ │ ├── CreatePostViewModel.kt │ │ │ │ │ └── CreatePostViewModelFactory.kt │ │ │ │ └── read │ │ │ │ │ ├── ReadPostFragment.kt │ │ │ │ │ ├── ReadPostViewModel.kt │ │ │ │ │ ├── ReadPostViewModelFactory.kt │ │ │ │ │ └── SetRatingFragment.kt │ │ │ ├── sign_in │ │ │ │ ├── SignInFragment.kt │ │ │ │ ├── SignInViewModel.kt │ │ │ │ └── SignInViewModelFactory.kt │ │ │ └── users │ │ │ │ ├── UsersAdapter.kt │ │ │ │ ├── UsersFragment.kt │ │ │ │ ├── UsersViewModel.kt │ │ │ │ ├── UsersViewModelFactory.kt │ │ │ │ ├── profile │ │ │ │ ├── UserProfileFragment.kt │ │ │ │ ├── UserProfileViewModel.kt │ │ │ │ └── UserProfileViewModelFactory.kt │ │ │ │ └── update │ │ │ │ ├── UpdateUserFragment.kt │ │ │ │ ├── UpdateUserViewModel.kt │ │ │ │ └── UpdateUserViewModelFactory.kt │ │ │ └── util │ │ │ ├── BindingAdapters.kt │ │ │ ├── Constants.kt │ │ │ ├── DateUtils.kt │ │ │ ├── DocumentSnapshotUtils.kt │ │ │ ├── DomainUtils.kt │ │ │ ├── DynamicLinksUtils.kt │ │ │ ├── InjectorUtils.kt │ │ │ ├── ObservableViewModel.kt │ │ │ ├── OnFocusChangeListener.kt │ │ │ └── QuerySnapshotUtils.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── background_all_corners_rounded_secondary.xml │ │ ├── background_bottomsheet.xml │ │ ├── background_bottomsheet_stroke.xml │ │ ├── background_shadow_bottom_to_top.xml │ │ ├── background_splash.xml │ │ ├── baseline_bookmark_18.xml │ │ ├── color_bottom_navigation.xml │ │ ├── color_side_navigation.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_undraw_camera_mg5h.xml │ │ ├── ic_undraw_ideas_s70l.xml │ │ ├── ic_undraw_reading_0re1.xml │ │ ├── outline_access_time_18.xml │ │ ├── outline_add_18.xml │ │ ├── outline_add_photo_alternate_18.xml │ │ ├── outline_arrow_forward_18.xml │ │ ├── outline_bookmark_border_18.xml │ │ ├── outline_bookmarks_18.xml │ │ ├── outline_close_24.xml │ │ ├── outline_cloud_download_18.xml │ │ ├── outline_drag_handle_24.xml │ │ ├── outline_edit_18.xml │ │ ├── outline_exit_to_app_18.xml │ │ ├── outline_explore_24.xml │ │ ├── outline_feedback_18.xml │ │ ├── outline_info_18.xml │ │ ├── outline_info_24.xml │ │ ├── outline_library_books_18.xml │ │ ├── outline_location_on_18.xml │ │ ├── outline_more_horiz_24.xml │ │ ├── outline_people_outline_18.xml │ │ ├── outline_share_18.xml │ │ ├── outline_short_text_18.xml │ │ ├── outline_subject_18.xml │ │ └── outline_whatshot_24.xml │ │ ├── font │ │ ├── roboto.xml │ │ ├── roboto_light.xml │ │ ├── roboto_medium.xml │ │ └── roboto_thin.xml │ │ ├── layout-land │ │ └── activity_main.xml │ │ ├── layout-v21 │ │ ├── fragment_explore.xml │ │ ├── fragment_user_profile.xml │ │ ├── item_topic.xml │ │ ├── layout_read_my_rating_section.xml │ │ ├── layout_read_post_content_section.xml │ │ └── layout_read_post_footer_section.xml │ │ ├── layout-w600dp │ │ ├── layout_create_post_select_topic_section.xml │ │ ├── layout_explore_topics_section.xml │ │ ├── layout_feed_list.xml │ │ ├── layout_posts_list.xml │ │ └── layout_users_list.xml │ │ ├── layout-w900dp │ │ ├── layout_create_post_select_topic_section.xml │ │ ├── layout_explore_topics_section.xml │ │ ├── layout_feed_list.xml │ │ ├── layout_posts_list.xml │ │ └── layout_users_list.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_create_post.xml │ │ ├── fragment_explore.xml │ │ ├── fragment_feed.xml │ │ ├── fragment_more.xml │ │ ├── fragment_posts.xml │ │ ├── fragment_read_post.xml │ │ ├── fragment_set_rating.xml │ │ ├── fragment_sign_in.xml │ │ ├── fragment_update_user.xml │ │ ├── fragment_user_profile.xml │ │ ├── fragment_users.xml │ │ ├── item_post.xml │ │ ├── item_suggestion.xml │ │ ├── item_topic.xml │ │ ├── item_user.xml │ │ ├── layout_appbar.xml │ │ ├── layout_create_post_actions_section.xml │ │ ├── layout_create_post_content_section.xml │ │ ├── layout_create_post_loading_screen.xml │ │ ├── layout_create_post_select_topic_section.xml │ │ ├── layout_explore_suggestions_section.xml │ │ ├── layout_explore_topics_section.xml │ │ ├── layout_feed_list.xml │ │ ├── layout_header.xml │ │ ├── layout_more_about_section.xml │ │ ├── layout_more_actions_section.xml │ │ ├── layout_more_footer_section.xml │ │ ├── layout_more_session_section.xml │ │ ├── layout_more_updates_section.xml │ │ ├── layout_more_user_section.xml │ │ ├── layout_posts_list.xml │ │ ├── layout_read_my_rating_section.xml │ │ ├── layout_read_post_content_section.xml │ │ ├── layout_read_post_footer_section.xml │ │ ├── layout_update_user_content.xml │ │ ├── layout_update_user_loading_screen.xml │ │ ├── layout_user_profile_actions_section.xml │ │ ├── layout_user_profile_details_section.xml │ │ ├── layout_user_profile_header_section.xml │ │ └── layout_users_list.xml │ │ ├── menu │ │ ├── main.xml │ │ └── navigation.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── navigation │ │ └── navigation.xml │ │ ├── values-night │ │ ├── colors.xml │ │ └── styles.xml │ │ ├── values-pt │ │ └── strings.xml │ │ ├── values-v21 │ │ └── dimens.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── font_certs.xml │ │ ├── ic_launcher_background.xml │ │ ├── preloaded_fonts.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── backup_descriptor.xml │ └── test │ └── java │ └── io │ └── github │ └── horaciocome1 │ └── reaque │ └── ExampleUnitTest.kt ├── build.gradle ├── docs ├── DONATE.md ├── LICENSE ├── PRIVACY_POLICY.md ├── TERMS_AND_CONDITIONS.md └── diagrams │ ├── reaque-architecture.jpg │ └── use_case.png ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── logo.png ├── mock1.png ├── mock2.png ├── mock3.png ├── screen1.png ├── screen2.png ├── screen3.png ├── screen4.png ├── screen5.png ├── screen6.png ├── screen7.png └── screen8.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/copyright/horaciocome1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/dictionaries/horaciocome1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | comé 5 | flávio 6 | horácio 7 | júnior 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "122712633760", 4 | "firebase_url": "https://reaque.firebaseio.com", 5 | "project_id": "reaque", 6 | "storage_bucket": "reaque.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:122712633760:android:282dab5331ca358d", 12 | "android_client_info": { 13 | "package_name": "io.github.horaciocome1.reaque" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "122712633760-kb5oics5qg5135lgqrig7tubkvk2c6h6.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "io.github.horaciocome1.reaque", 22 | "certificate_hash": "aa220d6f23b8cdcdd4a9fec2368cf166834b15f3" 23 | } 24 | }, 25 | { 26 | "client_id": "122712633760-pm82l3ctb5pep0njfgmhgjv945c7j6cp.apps.googleusercontent.com", 27 | "client_type": 1, 28 | "android_info": { 29 | "package_name": "io.github.horaciocome1.reaque", 30 | "certificate_hash": "5c79a18f386941942c4f5c6df4502319063de1f7" 31 | } 32 | }, 33 | { 34 | "client_id": "122712633760-66sqghv6p3dldgp9d37ps3li4ar37c6a.apps.googleusercontent.com", 35 | "client_type": 3 36 | } 37 | ], 38 | "api_key": [ 39 | { 40 | "current_key": "AIzaSyBsyD3INiI46fNPu0nbj53Qcrs5ab1-Ih4" 41 | } 42 | ], 43 | "services": { 44 | "appinvite_service": { 45 | "other_platform_oauth_client": [ 46 | { 47 | "client_id": "122712633760-66sqghv6p3dldgp9d37ps3li4ar37c6a.apps.googleusercontent.com", 48 | "client_type": 3 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | ], 55 | "configuration_version": "1" 56 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class namePostsFragment to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file namePostsFragment. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | # Firebase auth 24 | -keepattributes Signature 25 | -keepattributes *Annotation* -------------------------------------------------------------------------------- /app/src/androidTest/java/io/github/horaciocome1/reaque/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque 17 | 18 | import androidx.test.InstrumentationRegistry 19 | import androidx.test.runner.AndroidJUnit4 20 | import org.junit.Assert.assertEquals 21 | import org.junit.Test 22 | import org.junit.runner.RunWith 23 | 24 | /** 25 | * Instrumented test, which will execute on an Android device. 26 | * 27 | * See [testing documentation](http://d.android.com/tools/testing). 28 | */ 29 | @RunWith(AndroidJUnit4::class) 30 | class ExampleInstrumentedTest { 31 | @Test 32 | fun useAppContext() { 33 | // Context of the app under test. 34 | val appContext = InstrumentationRegistry.getTargetContext() 35 | assertEquals("io.github.horaciocome1.reaque", appContext.packageName) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/bookmarks/BookmarksInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.bookmarks 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.google.android.gms.tasks.Task 5 | import io.github.horaciocome1.reaque.data.posts.Post 6 | 7 | interface BookmarksInterface { 8 | 9 | fun bookmark(post: Post, onCompleteListener: (Task?) -> Unit) 10 | 11 | fun unBookmark(post: Post, onCompleteListener: (Task?) -> Unit) 12 | 13 | fun get(): LiveData> 14 | 15 | fun isBookmarked(post: Post): LiveData 16 | 17 | fun hasBookmarks(): LiveData 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/bookmarks/BookmarksRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.bookmarks 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.posts.Post 5 | 6 | class BookmarksRepository private constructor( 7 | private val service: BookmarksService 8 | ) : BookmarksInterface { 9 | 10 | override fun bookmark(post: Post, onCompleteListener: (Task?) -> Unit) = 11 | service.bookmark(post, onCompleteListener) 12 | 13 | override fun unBookmark(post: Post, onCompleteListener: (Task?) -> Unit) = 14 | service.unBookmark(post, onCompleteListener) 15 | 16 | override fun get() = service.get() 17 | 18 | override fun isBookmarked(post: Post) = service.isBookmarked(post) 19 | 20 | override fun hasBookmarks() = service.hasBookmarks() 21 | 22 | companion object { 23 | 24 | @Volatile 25 | private var instance: BookmarksRepository? = null 26 | 27 | fun getInstance(service: BookmarksService) = instance ?: synchronized(this) { 28 | instance ?: BookmarksRepository(service) 29 | .also { 30 | instance = it 31 | } 32 | } 33 | 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/configurations/ConfigurationsInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.configurations 2 | 3 | import androidx.lifecycle.LiveData 4 | 5 | interface ConfigurationsInterface { 6 | 7 | fun isUpdateAvailable(): LiveData 8 | 9 | fun getLatestVersionName(): LiveData 10 | 11 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/configurations/ConfigurationsRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.configurations 2 | 3 | class ConfigurationsRepository private constructor( 4 | private val service: ConfigurationsService 5 | ) : ConfigurationsInterface { 6 | 7 | override fun isUpdateAvailable() = service.isUpdateAvailable() 8 | 9 | override fun getLatestVersionName() = service.getLatestVersionName() 10 | 11 | companion object { 12 | 13 | @Volatile 14 | private var instance: ConfigurationsRepository? = null 15 | 16 | fun getInstance(service: ConfigurationsService) = instance ?: synchronized(this) { 17 | instance ?: ConfigurationsRepository(service) 18 | .also { 19 | instance = it 20 | } 21 | } 22 | 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/configurations/ConfigurationsService.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.configurations 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import com.google.firebase.auth.FirebaseAuth 6 | import com.google.firebase.firestore.FirebaseFirestore 7 | import io.github.horaciocome1.reaque.BuildConfig 8 | 9 | class ConfigurationsService : ConfigurationsInterface { 10 | 11 | private val versionCode: Int by lazy { 12 | BuildConfig.VERSION_CODE 13 | } 14 | 15 | val auth: FirebaseAuth by lazy { 16 | FirebaseAuth.getInstance() 17 | } 18 | 19 | private val db: FirebaseFirestore by lazy { 20 | FirebaseFirestore.getInstance() 21 | } 22 | 23 | private val isUpdateAvailable: MutableLiveData by lazy { 24 | MutableLiveData() 25 | .apply { 26 | value = false 27 | } 28 | } 29 | 30 | private val latestVersionName: MutableLiveData by lazy { 31 | MutableLiveData() 32 | .apply { 33 | value = "" 34 | } 35 | } 36 | 37 | override fun isUpdateAvailable(): LiveData { 38 | isUpdateAvailable.value = false 39 | db.document("configurations/default") 40 | .addSnapshotListener { snapshot, exception -> 41 | if ( 42 | exception == null 43 | && snapshot != null 44 | && snapshot.contains("version_code") 45 | ) 46 | isUpdateAvailable.value = versionCode < snapshot["version_code"].toString() 47 | .toInt() 48 | } 49 | return isUpdateAvailable 50 | } 51 | 52 | override fun getLatestVersionName(): LiveData { 53 | db.document("configurations/default") 54 | .addSnapshotListener { snapshot, exception -> 55 | if ( 56 | exception == null 57 | && snapshot != null 58 | && snapshot.contains("version_name") 59 | ) 60 | latestVersionName.value = snapshot["version_name"].toString() 61 | } 62 | return latestVersionName 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/feed/FeedInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.feed 2 | 3 | import androidx.lifecycle.LiveData 4 | import io.github.horaciocome1.reaque.data.posts.Post 5 | 6 | interface FeedInterface { 7 | 8 | fun get(): LiveData> 9 | 10 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/feed/FeedRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.feed 2 | 3 | class FeedRepository private constructor( 4 | private val service: FeedService 5 | ) : FeedInterface { 6 | 7 | override fun get() = service.get() 8 | 9 | companion object { 10 | 11 | @Volatile 12 | private var instance: FeedRepository? = null 13 | 14 | fun getInstance(service: FeedService) = instance ?: synchronized(this) { 15 | instance ?: FeedRepository(service) 16 | .also { 17 | instance = it 18 | } 19 | } 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/feed/FeedService.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.feed 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import com.google.firebase.auth.FirebaseAuth 6 | import com.google.firebase.firestore.FirebaseFirestore 7 | import com.google.firebase.firestore.Query 8 | import io.github.horaciocome1.reaque.data.posts.Post 9 | import io.github.horaciocome1.reaque.util.posts 10 | 11 | class FeedService : FeedInterface { 12 | 13 | private val db: FirebaseFirestore by lazy { 14 | FirebaseFirestore.getInstance() 15 | } 16 | 17 | private val auth: FirebaseAuth by lazy { 18 | FirebaseAuth.getInstance() 19 | } 20 | 21 | private var _posts = mutableListOf() 22 | 23 | private val posts: MutableLiveData> by lazy { 24 | MutableLiveData>().apply { 25 | value = mutableListOf() 26 | } 27 | } 28 | 29 | override fun get(): LiveData> { 30 | if (auth.currentUser == null) 31 | auth.addAuthStateListener { 32 | if ( 33 | _posts.isEmpty() 34 | && it.currentUser != null 35 | && _posts.isEmpty() 36 | ) 37 | getFeed() 38 | } 39 | else if (_posts.isEmpty()) 40 | getFeed() 41 | return posts 42 | } 43 | 44 | private fun getFeed() { 45 | db.collection("users/${auth.currentUser!!.uid}/feed") 46 | .orderBy("timestamp", Query.Direction.DESCENDING) 47 | .limit(100) 48 | .get() 49 | .addOnSuccessListener { 50 | if (it != null) { 51 | _posts = it.posts 52 | posts.value = _posts 53 | } 54 | } 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/posts/Post.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.data.posts 17 | 18 | import com.google.firebase.Timestamp 19 | import io.github.horaciocome1.reaque.data.topics.Topic 20 | import io.github.horaciocome1.reaque.data.users.User 21 | import io.github.horaciocome1.reaque.util.string 22 | 23 | data class Post(var id: String) { 24 | 25 | var title = "" 26 | var date = "" 27 | var user = User("") 28 | var pic = "" 29 | var message = "" 30 | var topic = Topic("") 31 | var timestamp = Timestamp.now() 32 | set(value) { 33 | date = value.string 34 | field = value 35 | } 36 | var score: Float = 1f - (1f / timestamp.seconds) 37 | var rating = 0f 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/posts/PostsInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.posts 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.google.android.gms.tasks.Task 5 | import io.github.horaciocome1.reaque.data.topics.Topic 6 | import io.github.horaciocome1.reaque.data.users.User 7 | 8 | interface PostsInterface { 9 | 10 | fun create(post: Post, onCompleteListener: (Task?) -> Unit) 11 | 12 | fun get(post: Post): LiveData 13 | 14 | fun get(user: User): LiveData> 15 | 16 | fun get(topic: Topic): LiveData> 17 | 18 | fun getTop10(): LiveData> 19 | 20 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/posts/PostsRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.posts 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.topics.Topic 5 | import io.github.horaciocome1.reaque.data.users.User 6 | 7 | class PostsRepository private constructor( 8 | private val service: PostsService 9 | ) : PostsInterface { 10 | 11 | override fun create(post: Post, onCompleteListener: (Task?) -> Unit) = 12 | service.create(post, onCompleteListener) 13 | 14 | override fun get(post: Post) = service.get(post) 15 | 16 | override fun get(user: User) = service.get(user) 17 | 18 | override fun get(topic: Topic) = service.get(topic) 19 | 20 | override fun getTop10() = service.getTop10() 21 | 22 | companion object { 23 | 24 | @Volatile 25 | private var instance: PostsRepository? = null 26 | 27 | fun getInstance(service: PostsService) = instance ?: synchronized(this) { 28 | instance ?: PostsRepository(service) 29 | .also { 30 | instance = it 31 | } 32 | } 33 | 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/ratings/RatingsInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.ratings 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.google.android.gms.tasks.Task 5 | import io.github.horaciocome1.reaque.data.posts.Post 6 | 7 | interface RatingsInterface { 8 | 9 | fun set(post: Post, value: Int, onCompleteListener: (Task?) -> Unit) 10 | 11 | fun get(post: Post): LiveData 12 | 13 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/ratings/RatingsRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.ratings 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.posts.Post 5 | 6 | class RatingsRepository private constructor(private val service: RatingsService) : RatingsInterface { 7 | 8 | override fun set(post: Post, value: Int, onCompleteListener: (Task?) -> Unit) = 9 | service.set(post, value, onCompleteListener) 10 | 11 | override fun get(post: Post) = service.get(post) 12 | 13 | companion object { 14 | 15 | @Volatile 16 | private var instance: RatingsRepository? = null 17 | 18 | fun getInstance(service: RatingsService) = instance ?: synchronized(this) { 19 | instance ?: RatingsRepository(service) 20 | .also { 21 | instance = it 22 | } 23 | } 24 | 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/ratings/RatingsService.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.ratings 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import com.google.android.gms.tasks.Task 6 | import com.google.firebase.auth.FirebaseAuth 7 | import com.google.firebase.firestore.FirebaseFirestore 8 | import com.google.firebase.firestore.SetOptions 9 | import io.github.horaciocome1.reaque.data.posts.Post 10 | import io.github.horaciocome1.reaque.util.map 11 | import io.github.horaciocome1.reaque.util.user 12 | 13 | class RatingsService : RatingsInterface { 14 | 15 | private val db: FirebaseFirestore by lazy { 16 | FirebaseFirestore.getInstance() 17 | } 18 | 19 | private val auth: FirebaseAuth by lazy { 20 | FirebaseAuth.getInstance() 21 | } 22 | 23 | private val rating: MutableLiveData by lazy { 24 | MutableLiveData().apply { 25 | value = 0 26 | } 27 | } 28 | 29 | override fun set(post: Post, value: Int, onCompleteListener: (Task?) -> Unit) { 30 | if ( 31 | post.id.isNotBlank() 32 | && value >= 1 33 | && value <= 5 34 | && auth.currentUser != null 35 | ) { 36 | val data = auth.currentUser!!.user.map 37 | .plus("value" to value) 38 | .plus( 39 | "post" to mapOf( 40 | "id" to post.id 41 | ) 42 | ) 43 | db.document( 44 | "posts/${post.id}" + 45 | "/ratings/${auth.currentUser!!.uid}" 46 | ) 47 | .set(data, SetOptions.merge()) 48 | .addOnCompleteListener(onCompleteListener) 49 | } 50 | } 51 | 52 | override fun get(post: Post): LiveData { 53 | rating.value = 0 54 | if (post.id.isNotBlank() && auth.currentUser != null) 55 | db.document( 56 | "posts/${post.id}" + 57 | "/ratings/${auth.currentUser!!.uid}" 58 | ) 59 | .addSnapshotListener { snapshot, exception -> 60 | if ( 61 | exception == null 62 | && snapshot != null 63 | && snapshot.contains("value") 64 | ) 65 | rating.value = snapshot["value"] 66 | .toString() 67 | .toInt() 68 | } 69 | return rating 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/readings/ReadingsInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.readings 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.posts.Post 5 | 6 | interface ReadingsInterface { 7 | 8 | fun read(post: Post, onCompleteListener: (Task?) -> Unit) 9 | 10 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/readings/ReadingsRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.readings 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.posts.Post 5 | 6 | class ReadingsRepository private constructor( 7 | private val service: ReadingsService 8 | ) : ReadingsInterface { 9 | 10 | override fun read(post: Post, onCompleteListener: (Task?) -> Unit) = service.read(post, onCompleteListener) 11 | 12 | companion object { 13 | 14 | @Volatile 15 | private var instance: ReadingsRepository? = null 16 | 17 | fun getInstance(service: ReadingsService) = instance ?: synchronized(this) { 18 | instance ?: ReadingsRepository(service) 19 | .also { 20 | instance = it 21 | } 22 | } 23 | 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/readings/ReadingsService.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.readings 2 | 3 | import com.google.android.gms.tasks.Task 4 | import com.google.firebase.auth.FirebaseAuth 5 | import com.google.firebase.firestore.FieldValue 6 | import com.google.firebase.firestore.FirebaseFirestore 7 | import com.google.firebase.firestore.SetOptions 8 | import io.github.horaciocome1.reaque.data.posts.Post 9 | import io.github.horaciocome1.reaque.util.mapSimple 10 | 11 | class ReadingsService : ReadingsInterface { 12 | 13 | private val db: FirebaseFirestore by lazy { 14 | FirebaseFirestore.getInstance() 15 | } 16 | 17 | private val auth: FirebaseAuth by lazy { 18 | FirebaseAuth.getInstance() 19 | } 20 | 21 | private val increment: Map by lazy { 22 | val increment = FieldValue.increment(1) 23 | mapOf("readings" to increment) 24 | } 25 | 26 | override fun read(post: Post, onCompleteListener: (Task?) -> Unit) { 27 | if ( 28 | post.id.isNotBlank() 29 | && auth.currentUser != null 30 | ) { 31 | val readingRef = db.document( 32 | "users/${auth.currentUser!!.uid}" + 33 | "/readings/${post.id}" 34 | ) 35 | val postRef = db.document("posts/${post.id}") 36 | db.runBatch { 37 | it.set(readingRef, post.mapSimple) 38 | it.set(postRef, increment, SetOptions.merge()) 39 | }.addOnCompleteListener(onCompleteListener) 40 | } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/shares/SharesInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.shares 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.posts.Post 5 | 6 | interface SharesInterface { 7 | 8 | fun share(post: Post, onCompleteListener: (Task?) -> Unit) 9 | 10 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/shares/SharesRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.shares 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.posts.Post 5 | 6 | class SharesRepository private constructor( 7 | private val service: SharesService 8 | ) : SharesInterface { 9 | 10 | override fun share(post: Post, onCompleteListener: (Task?) -> Unit) = service.share(post, onCompleteListener) 11 | 12 | companion object { 13 | 14 | @Volatile 15 | private var instance: SharesRepository? = null 16 | 17 | fun getInstance(service: SharesService) = instance ?: synchronized(this) { 18 | instance ?: SharesRepository(service) 19 | .also { 20 | instance = it 21 | } 22 | } 23 | 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/shares/SharesService.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.shares 2 | 3 | import com.google.android.gms.tasks.Task 4 | import com.google.firebase.auth.FirebaseAuth 5 | import com.google.firebase.firestore.FieldValue 6 | import com.google.firebase.firestore.FirebaseFirestore 7 | import com.google.firebase.firestore.SetOptions 8 | import io.github.horaciocome1.reaque.data.posts.Post 9 | import io.github.horaciocome1.reaque.util.mapSimple 10 | 11 | class SharesService : SharesInterface { 12 | 13 | private val db: FirebaseFirestore by lazy { 14 | FirebaseFirestore.getInstance() 15 | } 16 | 17 | private val auth: FirebaseAuth by lazy { 18 | FirebaseAuth.getInstance() 19 | } 20 | 21 | private val increment: Map by lazy { 22 | val increment = FieldValue.increment(1) 23 | mapOf("shares" to increment) 24 | } 25 | 26 | override fun share(post: Post, onCompleteListener: (Task?) -> Unit) { 27 | if (post.id.isNotBlank() && auth.currentUser != null) { 28 | val readingRef = db.document( 29 | "users/${auth.currentUser!!.uid}" + 30 | "/shares/${post.id}" 31 | ) 32 | val postRef = db.document("posts/${post.id}") 33 | db.runBatch { 34 | it.set(readingRef, post.mapSimple) 35 | it.set(postRef, increment, SetOptions.merge()) 36 | }.addOnCompleteListener(onCompleteListener) 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/storage/StorageRepository.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.data.storage 17 | 18 | import android.net.Uri 19 | import io.github.horaciocome1.reaque.data.topics.Topic 20 | 21 | class StorageRepository private constructor( 22 | private val webservice: StorageService 23 | ) { 24 | 25 | fun uploadImage(imageUri: Uri, topic: Topic, onSuccessListener: (Uri?) -> Unit) = 26 | webservice.upload(imageUri, topic, onSuccessListener) 27 | 28 | companion object { 29 | 30 | @Volatile 31 | private var instance: StorageRepository? = null 32 | 33 | fun getInstance(webservice: StorageService) = instance ?: synchronized(this) { 34 | instance ?: StorageRepository(webservice) 35 | .also { 36 | instance = it 37 | } 38 | } 39 | 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/storage/StorageService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.data.storage 17 | 18 | import android.net.Uri 19 | import com.google.android.gms.tasks.Continuation 20 | import com.google.android.gms.tasks.Task 21 | import com.google.firebase.storage.FirebaseStorage 22 | import com.google.firebase.storage.UploadTask 23 | import io.github.horaciocome1.reaque.data.topics.Topic 24 | 25 | class StorageService { 26 | 27 | private val storage: FirebaseStorage by lazy { 28 | FirebaseStorage.getInstance() 29 | } 30 | 31 | fun upload(imageUri: Uri, topic: Topic, onSuccessListener: (Uri?) -> Unit) { 32 | if ( 33 | imageUri != Uri.EMPTY 34 | && topic.id.isNotBlank() 35 | ) { 36 | val path = "images/${topic.id}/${imageUri.lastPathSegment}" 37 | val ref = storage.reference.child(path) 38 | ref.putFile(imageUri) 39 | .continueWithTask(Continuation> { task -> 40 | if (!task.isSuccessful) 41 | task.exception?.let { 42 | throw it 43 | } 44 | return@Continuation ref.downloadUrl 45 | }) 46 | .addOnSuccessListener(onSuccessListener) 47 | } 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/subscriptions/SubscriptionsInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.subscriptions 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.google.android.gms.tasks.Task 5 | import io.github.horaciocome1.reaque.data.users.User 6 | 7 | interface SubscriptionsInterface { 8 | 9 | fun subscribe(user: User, onCompleteListener: (Task?) -> Unit) 10 | 11 | fun unSubscribe(user: User, onCompleteListener: (Task?) -> Unit) 12 | 13 | fun getSubscriptions(user: User): LiveData> 14 | 15 | fun getSubscribers(user: User): LiveData> 16 | 17 | fun amSubscribedTo(user: User): LiveData 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/subscriptions/SubscriptionsRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.subscriptions 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.users.User 5 | 6 | class SubscriptionsRepository private constructor( 7 | private val service: SubscriptionsService 8 | ) : SubscriptionsInterface { 9 | 10 | override fun subscribe(user: User, onCompleteListener: (Task?) -> Unit) = 11 | service.subscribe(user, onCompleteListener) 12 | 13 | override fun unSubscribe(user: User, onCompleteListener: (Task?) -> Unit) = 14 | service.unSubscribe(user, onCompleteListener) 15 | 16 | override fun getSubscriptions(user: User) = service.getSubscriptions(user) 17 | 18 | override fun getSubscribers(user: User) = service.getSubscribers(user) 19 | 20 | override fun amSubscribedTo(user: User) = service.amSubscribedTo(user) 21 | 22 | companion object { 23 | 24 | private var instance: SubscriptionsRepository? = null 25 | 26 | fun getInstance(service: SubscriptionsService) = instance ?: synchronized(this) { 27 | instance ?: SubscriptionsRepository(service) 28 | .also { 29 | instance = it 30 | } 31 | } 32 | 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/topics/Topic.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.data.topics 17 | 18 | data class Topic(var id: String) { 19 | 20 | var title = "" 21 | var pic = "" 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/topics/TopicsRepository.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.data.topics 17 | 18 | import androidx.lifecycle.LiveData 19 | 20 | class TopicsRepository private constructor( 21 | service: TopicsService 22 | ) { 23 | 24 | val notEmptyTopics: LiveData> by lazy { 25 | service.notEmptyTopics 26 | } 27 | 28 | val topics: LiveData> by lazy { 29 | service.topics 30 | } 31 | 32 | companion object { 33 | 34 | @Volatile 35 | private var instance: TopicsRepository? = null 36 | 37 | fun getInstance(topicsService: TopicsService) = instance ?: synchronized(this) { 38 | instance ?: TopicsRepository(topicsService) 39 | .also { 40 | instance = it 41 | } 42 | } 43 | 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/topics/TopicsService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.data.topics 17 | 18 | import androidx.lifecycle.MutableLiveData 19 | import com.google.firebase.firestore.CollectionReference 20 | import com.google.firebase.firestore.FirebaseFirestore 21 | import com.google.firebase.firestore.Query 22 | import io.github.horaciocome1.reaque.util.topics 23 | 24 | class TopicsService { 25 | 26 | private val ref: CollectionReference by lazy { 27 | FirebaseFirestore.getInstance().collection("topics") 28 | } 29 | 30 | private var _notEmptyTopics = mutableListOf() 31 | 32 | val notEmptyTopics = MutableLiveData>() 33 | get() { 34 | if (_notEmptyTopics.isEmpty()) 35 | ref.whereGreaterThan("score", 0) 36 | .orderBy("score", Query.Direction.DESCENDING) 37 | .get() 38 | .addOnSuccessListener { 39 | if (it != null) { 40 | _notEmptyTopics = it.topics 41 | field.value = _notEmptyTopics 42 | } 43 | } 44 | return field 45 | } 46 | 47 | private var _topics = mutableListOf() 48 | 49 | val topics = MutableLiveData>() 50 | get() { 51 | if (_topics.isEmpty()) 52 | ref.orderBy("title", Query.Direction.ASCENDING) 53 | .get() 54 | .addOnSuccessListener { 55 | if (it != null) { 56 | _topics = it.topics 57 | field.value = _topics 58 | } 59 | } 60 | return field 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/users/User.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.data.users 17 | 18 | import io.github.horaciocome1.reaque.util.string 19 | 20 | data class User(var id: String) { 21 | 22 | var name = "" 23 | var bio = "" 24 | var pic = "" 25 | var address = "" 26 | var email = "" 27 | var since = "" 28 | var timestamp = com.google.firebase.Timestamp.now() 29 | set(value) { 30 | since = value.string 31 | field = value 32 | } 33 | var topTopic = "" 34 | var posts = "0" 35 | var subscribers = "0" 36 | var subscriptions = "0" 37 | var score = 0f 38 | 39 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/users/UsersInterface.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.users 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.google.android.gms.tasks.Task 5 | import io.github.horaciocome1.reaque.data.topics.Topic 6 | 7 | interface UsersInterface { 8 | 9 | fun update(user: User, onCompleteListener: (Task?) -> Unit) 10 | 11 | fun get(user: User): LiveData 12 | 13 | fun get(topic: Topic): LiveData> 14 | 15 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/data/users/UsersRepository.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.data.users 2 | 3 | import com.google.android.gms.tasks.Task 4 | import io.github.horaciocome1.reaque.data.topics.Topic 5 | 6 | class UsersRepository private constructor( 7 | private val service: UsersService 8 | ) : UsersInterface { 9 | 10 | override fun update(user: User, onCompleteListener: (Task?) -> Unit) = 11 | service.update(user, onCompleteListener) 12 | 13 | override fun get(user: User) = service.get(user) 14 | 15 | override fun get(topic: Topic) = service.get(topic) 16 | 17 | companion object { 18 | 19 | @Volatile 20 | private var instance: UsersRepository? = null 21 | 22 | fun getInstance(service: UsersService) = instance ?: synchronized(this) { 23 | instance ?: UsersRepository(service) 24 | .also { 25 | instance = it 26 | } 27 | } 28 | 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/explore/ExploreFragment.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.explore 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | import androidx.lifecycle.Observer 9 | import androidx.lifecycle.ViewModelProviders 10 | import io.github.horaciocome1.reaque.databinding.FragmentExploreBinding 11 | import io.github.horaciocome1.reaque.util.InjectorUtils 12 | import io.github.horaciocome1.simplerecyclerviewtouchlistener.addOnItemClickListener 13 | import io.github.horaciocome1.simplerecyclerviewtouchlistener.addOnItemLongPressListener 14 | import kotlinx.android.synthetic.main.layout_explore_suggestions_section.* 15 | import kotlinx.android.synthetic.main.layout_explore_topics_section.* 16 | 17 | class ExploreFragment : Fragment() { 18 | 19 | lateinit var binding: FragmentExploreBinding 20 | 21 | private val viewModel: ExploreViewModel by lazy { 22 | val factory = InjectorUtils.exploreViewModelFactory 23 | ViewModelProviders.of(this, factory)[ExploreViewModel::class.java] 24 | } 25 | 26 | override fun onCreateView( 27 | inflater: LayoutInflater, 28 | container: ViewGroup?, 29 | savedInstanceState: Bundle? 30 | ): View? { 31 | binding = FragmentExploreBinding.inflate(inflater, container, false) 32 | return binding.root 33 | } 34 | 35 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 36 | super.onViewCreated(view, savedInstanceState) 37 | posts_recyclerview.addOnItemClickListener(viewModel.onItemPostClickListener) 38 | topics_recyclerview.addOnItemClickListener(viewModel.onItemTopicClickListener) 39 | topics_recyclerview.addOnItemLongPressListener(viewModel.onItemTopicLongPressListener) 40 | } 41 | 42 | override fun onStart() { 43 | super.onStart() 44 | viewModel.notEmptyTopics 45 | .observe(this, Observer { 46 | binding.viewmodel = viewModel.setTopics(it) 47 | }) 48 | viewModel.top10 49 | .observe(this, Observer { 50 | binding.viewmodel = viewModel.setPosts(it) 51 | }) 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/explore/ExploreViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.explore 2 | 3 | import android.view.View 4 | import androidx.lifecycle.ViewModel 5 | import androidx.navigation.findNavController 6 | import io.github.horaciocome1.reaque.data.posts.Post 7 | import io.github.horaciocome1.reaque.data.posts.PostsRepository 8 | import io.github.horaciocome1.reaque.data.topics.Topic 9 | import io.github.horaciocome1.reaque.data.topics.TopicsRepository 10 | import io.github.horaciocome1.reaque.util.Constants 11 | 12 | class ExploreViewModel(topicsRepository: TopicsRepository, postsRepository: PostsRepository) : ViewModel() { 13 | 14 | var topics: List = mutableListOf() 15 | 16 | var posts: List = mutableListOf() 17 | 18 | val notEmptyTopics = topicsRepository.notEmptyTopics 19 | 20 | val top10 = postsRepository.getTop10() 21 | 22 | val onItemPostClickListener: (View, Int) -> Unit = { view, position -> 23 | if (posts.isNotEmpty()) { 24 | val directions = ExploreFragmentDirections 25 | .actionOpenReadPostFromExplore(posts[position].id) 26 | view.findNavController() 27 | .navigate(directions) 28 | } 29 | } 30 | 31 | val onItemTopicClickListener: (View, Int) -> Unit = { view, position -> 32 | if (posts.isNotEmpty()) { 33 | val directions = ExploreFragmentDirections 34 | .actionOpenPostsFromExplore(topics[position].id, Constants.TOPIC_POSTS_REQUEST) 35 | view.findNavController() 36 | .navigate(directions) 37 | } 38 | } 39 | 40 | val onItemTopicLongPressListener: (View, Int) -> Unit = { view, position -> 41 | if (posts.isNotEmpty()) { 42 | val directions = ExploreFragmentDirections 43 | .actionOpenUsersFromExplore(topics[position].id, Constants.TOPIC_USERS_REQUEST) 44 | view.findNavController() 45 | .navigate(directions) 46 | } 47 | } 48 | 49 | fun setTopics(topics: List): ExploreViewModel { 50 | this.topics = topics 51 | return this 52 | } 53 | 54 | fun setPosts(posts: List): ExploreViewModel { 55 | this.posts = posts 56 | return this 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/explore/ExploreViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.explore 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import io.github.horaciocome1.reaque.data.posts.PostsRepository 6 | import io.github.horaciocome1.reaque.data.topics.TopicsRepository 7 | 8 | class ExploreViewModelFactory( 9 | private val topicsRepository: TopicsRepository, 10 | private val postsRepository: PostsRepository 11 | ) : ViewModelProvider.NewInstanceFactory() { 12 | 13 | @Suppress("UNCHECKED_CAST") 14 | override fun create(modelClass: Class) = 15 | ExploreViewModel(topicsRepository, postsRepository) as T 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/explore/TopicsAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.ui.explore 17 | 18 | import android.view.LayoutInflater 19 | import android.view.View 20 | import android.view.ViewGroup 21 | import androidx.recyclerview.widget.RecyclerView 22 | import io.github.horaciocome1.reaque.data.topics.Topic 23 | import io.github.horaciocome1.reaque.databinding.ItemTopicBinding 24 | 25 | class TopicsAdapter(private val list: List) : 26 | RecyclerView.Adapter() { 27 | 28 | private lateinit var binding: ItemTopicBinding 29 | 30 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 31 | val inflater = LayoutInflater.from(parent.context) 32 | binding = ItemTopicBinding.inflate(inflater, parent, false) 33 | return ViewHolder(binding.root) 34 | } 35 | 36 | override fun getItemCount() = list.size 37 | 38 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 39 | binding.topic = list[position] 40 | } 41 | 42 | class ViewHolder(view: View) : RecyclerView.ViewHolder(view) 43 | 44 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/feed/FeedFragment.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.feed 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | import androidx.lifecycle.Observer 9 | import androidx.lifecycle.ViewModelProviders 10 | import io.github.horaciocome1.reaque.databinding.FragmentFeedBinding 11 | import io.github.horaciocome1.reaque.util.InjectorUtils 12 | import io.github.horaciocome1.simplerecyclerviewtouchlistener.addOnItemClickListener 13 | import kotlinx.android.synthetic.main.layout_feed_list.* 14 | 15 | class FeedFragment : Fragment() { 16 | 17 | lateinit var binding: FragmentFeedBinding 18 | 19 | private val viewModel: FeedViewModel by lazy { 20 | val factory = InjectorUtils.feedViewModelFactory 21 | ViewModelProviders.of(this, factory)[FeedViewModel::class.java] 22 | } 23 | 24 | override fun onCreateView( 25 | inflater: LayoutInflater, 26 | container: ViewGroup?, 27 | savedInstanceState: Bundle? 28 | ): View? { 29 | binding = FragmentFeedBinding.inflate(inflater, container, false) 30 | return binding.root 31 | } 32 | 33 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 34 | super.onViewCreated(view, savedInstanceState) 35 | posts_recyclerview.addOnItemClickListener(viewModel.onItemClickListener) 36 | } 37 | 38 | override fun onStart() { 39 | super.onStart() 40 | viewModel.feed 41 | .observe(this, Observer { 42 | binding.viewmodel = viewModel.setPosts(it) 43 | }) 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/feed/FeedViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.feed 2 | 3 | import android.view.View 4 | import androidx.lifecycle.ViewModel 5 | import androidx.navigation.findNavController 6 | import io.github.horaciocome1.reaque.data.feed.FeedRepository 7 | import io.github.horaciocome1.reaque.data.posts.Post 8 | 9 | class FeedViewModel(repository: FeedRepository) : ViewModel() { 10 | 11 | var posts: List = mutableListOf() 12 | 13 | val feed = repository.get() 14 | 15 | val onItemClickListener: (View, Int) -> Unit = { view, position -> 16 | if (posts.isNotEmpty()) { 17 | val directions = FeedFragmentDirections 18 | .actionOpenReadPostFromFeed(posts[position].id) 19 | view.findNavController() 20 | .navigate(directions) 21 | } 22 | } 23 | 24 | fun setPosts(posts: List): FeedViewModel { 25 | this.posts = posts 26 | return this 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/feed/FeedViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.feed 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import io.github.horaciocome1.reaque.data.feed.FeedRepository 6 | 7 | class FeedViewModelFactory(private val repository: FeedRepository) : 8 | ViewModelProvider.NewInstanceFactory() { 9 | 10 | @Suppress("UNCHECKED_CAST") 11 | override fun create(modelClass: Class): T = FeedViewModel(repository) as T 12 | 13 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/more/MoreViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.ui.more 17 | 18 | import androidx.lifecycle.ViewModel 19 | import androidx.lifecycle.ViewModelProvider 20 | import io.github.horaciocome1.reaque.data.bookmarks.BookmarksRepository 21 | import io.github.horaciocome1.reaque.data.configurations.ConfigurationsRepository 22 | 23 | class MoreViewModelFactory( 24 | private val bookmarksRepository: BookmarksRepository, 25 | private val configurationsRepository: ConfigurationsRepository 26 | ) : ViewModelProvider.NewInstanceFactory() { 27 | 28 | @Suppress("UNCHECKED_CAST") 29 | override fun create(modelClass: Class) = 30 | MoreViewModel(bookmarksRepository, configurationsRepository) as T 31 | 32 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/posts/PostsAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.ui.posts 17 | 18 | import android.view.LayoutInflater 19 | import android.view.View 20 | import android.view.ViewGroup 21 | import androidx.recyclerview.widget.RecyclerView 22 | import io.github.horaciocome1.reaque.data.posts.Post 23 | import io.github.horaciocome1.reaque.databinding.ItemPostBinding 24 | import io.github.horaciocome1.reaque.databinding.ItemSuggestionBinding 25 | 26 | class PostsAdapter(private val list: List) : RecyclerView.Adapter() { 27 | 28 | private lateinit var binding: ItemPostBinding 29 | 30 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 31 | val inflater = LayoutInflater.from(parent.context) 32 | binding = ItemPostBinding.inflate(inflater, parent, false) 33 | return ViewHolder(binding.root) 34 | } 35 | 36 | override fun getItemCount() = list.size 37 | 38 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 39 | binding.post = list[position] 40 | } 41 | 42 | class ViewHolder(view: View) : RecyclerView.ViewHolder(view) 43 | 44 | class SuggestionsAdapter(private val list: List) : 45 | RecyclerView.Adapter() { 46 | 47 | private lateinit var binding: ItemSuggestionBinding 48 | 49 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 50 | val inflater = LayoutInflater.from(parent.context) 51 | binding = ItemSuggestionBinding.inflate(inflater, parent, false) 52 | return ViewHolder(binding.root) 53 | } 54 | 55 | override fun getItemCount() = list.size 56 | 57 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 58 | binding.post = list[position] 59 | } 60 | 61 | class ViewHolder(view: View) : RecyclerView.ViewHolder(view) 62 | 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/posts/PostsFragment.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.posts 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | import androidx.lifecycle.Observer 9 | import androidx.lifecycle.ViewModelProviders 10 | import io.github.horaciocome1.reaque.databinding.FragmentPostsBinding 11 | import io.github.horaciocome1.reaque.util.InjectorUtils 12 | import io.github.horaciocome1.simplerecyclerviewtouchlistener.addOnItemClickListener 13 | import kotlinx.android.synthetic.main.layout_posts_list.* 14 | 15 | class PostsFragment : Fragment() { 16 | 17 | private lateinit var binding: FragmentPostsBinding 18 | 19 | private val viewModel: PostsViewModel by lazy { 20 | val factory = InjectorUtils.postsViewModelFactory 21 | ViewModelProviders.of(this, factory)[PostsViewModel::class.java] 22 | } 23 | 24 | override fun onCreateView( 25 | inflater: LayoutInflater, 26 | container: ViewGroup?, 27 | savedInstanceState: Bundle? 28 | ): View? { 29 | binding = FragmentPostsBinding.inflate(inflater, container, false) 30 | return binding.root 31 | } 32 | 33 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 34 | super.onViewCreated(view, savedInstanceState) 35 | posts_recyclerview.addOnItemClickListener(viewModel.onItemClickListener) 36 | } 37 | 38 | override fun onStart() { 39 | super.onStart() 40 | arguments?.let { bundle -> 41 | val args = PostsFragmentArgs.fromBundle(bundle) 42 | viewModel.get(args.parentId, args.requestId) 43 | .observe(this, Observer { 44 | binding.viewmodel = viewModel.setPosts(it) 45 | }) 46 | } 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/posts/PostsViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.posts 2 | 3 | import android.view.View 4 | import androidx.lifecycle.LiveData 5 | import androidx.lifecycle.ViewModel 6 | import androidx.navigation.findNavController 7 | import io.github.horaciocome1.reaque.data.bookmarks.BookmarksRepository 8 | import io.github.horaciocome1.reaque.data.posts.Post 9 | import io.github.horaciocome1.reaque.data.posts.PostsRepository 10 | import io.github.horaciocome1.reaque.data.topics.Topic 11 | import io.github.horaciocome1.reaque.data.users.User 12 | import io.github.horaciocome1.reaque.util.Constants 13 | 14 | class PostsViewModel( 15 | private val postsRepository: PostsRepository, 16 | private val bookmarksRepository: BookmarksRepository 17 | ) : ViewModel() { 18 | 19 | var posts: List = mutableListOf() 20 | 21 | val onItemClickListener: (View, Int) -> Unit = { view, position -> 22 | if (posts.isNotEmpty()) { 23 | val directions = PostsFragmentDirections 24 | .actionOpenReadPostFromPosts(posts[position].id) 25 | view.findNavController() 26 | .navigate(directions) 27 | } 28 | } 29 | 30 | fun setPosts(posts: List): PostsViewModel { 31 | this.posts = posts 32 | return this 33 | } 34 | 35 | 36 | fun get(parentId: String, requestId: String): LiveData> { 37 | return when (requestId) { 38 | Constants.TOPIC_POSTS_REQUEST -> postsRepository.get((Topic(parentId))) 39 | Constants.USER_POSTS_REQUEST -> postsRepository.get((User(parentId))) 40 | else -> bookmarksRepository.get() 41 | } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/posts/PostsViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.posts 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import io.github.horaciocome1.reaque.data.bookmarks.BookmarksRepository 6 | import io.github.horaciocome1.reaque.data.posts.PostsRepository 7 | 8 | class PostsViewModelFactory( 9 | private val postsRepository: PostsRepository, 10 | private val bookmarksRepository: BookmarksRepository 11 | ) : ViewModelProvider.NewInstanceFactory() { 12 | 13 | @Suppress("UNCHECKED_CAST") 14 | override fun create(modelClass: Class) = 15 | PostsViewModel(postsRepository, bookmarksRepository) as T 16 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/posts/create/CreatePostViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.posts.create 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import io.github.horaciocome1.reaque.data.posts.PostsRepository 6 | import io.github.horaciocome1.reaque.data.storage.StorageRepository 7 | import io.github.horaciocome1.reaque.data.topics.TopicsRepository 8 | 9 | class CreatePostViewModelFactory( 10 | private val postsRepository: PostsRepository, 11 | private val topicsRepository: TopicsRepository, 12 | private val storageRepository: StorageRepository 13 | ) : ViewModelProvider.NewInstanceFactory() { 14 | 15 | @Suppress("UNCHECKED_CAST") 16 | override fun create(modelClass: Class) = CreatePostViewModel( 17 | topicsRepository, 18 | postsRepository, 19 | storageRepository 20 | ) as T 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/posts/read/ReadPostViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.posts.read 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import io.github.horaciocome1.reaque.data.bookmarks.BookmarksRepository 6 | import io.github.horaciocome1.reaque.data.posts.PostsRepository 7 | import io.github.horaciocome1.reaque.data.ratings.RatingsRepository 8 | import io.github.horaciocome1.reaque.data.readings.ReadingsRepository 9 | import io.github.horaciocome1.reaque.data.shares.SharesRepository 10 | 11 | class ReadPostViewModelFactory( 12 | private val postsRepository: PostsRepository, 13 | private val readingsRepository: ReadingsRepository, 14 | private val sharesRepository: SharesRepository, 15 | private val ratingsRepository: RatingsRepository, 16 | private val bookmarksRepository: BookmarksRepository 17 | ) : ViewModelProvider.NewInstanceFactory() { 18 | 19 | @Suppress("UNCHECKED_CAST") 20 | override fun create(modelClass: Class) = ReadPostViewModel( 21 | postsRepository, 22 | readingsRepository, 23 | sharesRepository, 24 | ratingsRepository, 25 | bookmarksRepository 26 | ) as T 27 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/sign_in/SignInViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.sign_in 2 | 3 | import androidx.lifecycle.ViewModel 4 | import com.google.android.gms.auth.api.signin.GoogleSignIn 5 | import com.google.android.gms.auth.api.signin.GoogleSignInAccount 6 | import com.google.android.gms.auth.api.signin.GoogleSignInOptions 7 | import com.google.firebase.auth.FirebaseAuth 8 | import com.google.firebase.auth.GoogleAuthProvider 9 | import io.github.horaciocome1.reaque.R 10 | import io.github.horaciocome1.reaque.ui.MainActivity 11 | import io.github.horaciocome1.reaque.util.Constants 12 | 13 | class SignInViewModel : ViewModel() { 14 | 15 | private val auth: FirebaseAuth by lazy { 16 | FirebaseAuth.getInstance() 17 | } 18 | 19 | fun signInWithGoogle(fragment: SignInFragment) { 20 | val activity = fragment.activity 21 | if (activity is MainActivity) { 22 | val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 23 | .requestIdToken(activity.getString(R.string.default_web_client_id)) 24 | .requestEmail() 25 | .build() 26 | val googleSignInClient = GoogleSignIn.getClient(activity, gso) 27 | fragment.startActivityForResult( 28 | googleSignInClient?.signInIntent, 29 | Constants.GOOGLE_SIGN_IN_REQUEST_CODE 30 | ) 31 | } 32 | } 33 | 34 | fun firebaseAuthWithGoogle( 35 | account: GoogleSignInAccount, 36 | listener: (Any) -> Unit 37 | ) { 38 | val credential = GoogleAuthProvider.getCredential(account.idToken, null) 39 | auth.signInWithCredential(credential) 40 | .addOnSuccessListener(listener) 41 | .addOnFailureListener(listener) 42 | } 43 | 44 | 45 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/sign_in/SignInViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.sign_in 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | 6 | class SignInViewModelFactory : ViewModelProvider.NewInstanceFactory() { 7 | 8 | @Suppress("UNCHECKED_CAST") 9 | override fun create(modelClass: Class) = SignInViewModel() as T 10 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/users/UsersAdapter.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.users 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import io.github.horaciocome1.reaque.data.users.User 8 | import io.github.horaciocome1.reaque.databinding.ItemUserBinding 9 | 10 | class UsersAdapter(private val list: List) : RecyclerView.Adapter() { 11 | 12 | private lateinit var binding: ItemUserBinding 13 | 14 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 15 | val inflater = LayoutInflater.from(parent.context) 16 | binding = ItemUserBinding.inflate(inflater, parent, false) 17 | return ViewHolder(binding.root) 18 | } 19 | 20 | override fun getItemCount() = list.size 21 | 22 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 23 | binding.user = list[position] 24 | } 25 | 26 | class ViewHolder(view: View) : RecyclerView.ViewHolder(view) 27 | 28 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/users/UsersFragment.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.users 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | import androidx.lifecycle.Observer 9 | import androidx.lifecycle.ViewModelProviders 10 | import io.github.horaciocome1.reaque.databinding.FragmentUsersBinding 11 | import io.github.horaciocome1.reaque.util.InjectorUtils 12 | import io.github.horaciocome1.simplerecyclerviewtouchlistener.addOnItemClickListener 13 | import kotlinx.android.synthetic.main.layout_users_list.* 14 | 15 | class UsersFragment : Fragment() { 16 | 17 | private lateinit var binding: FragmentUsersBinding 18 | 19 | private val viewModel: UsersViewModel by lazy { 20 | val factory = InjectorUtils.usersViewModelFactory 21 | ViewModelProviders.of(this, factory)[UsersViewModel::class.java] 22 | } 23 | 24 | override fun onCreateView( 25 | inflater: LayoutInflater, 26 | container: ViewGroup?, 27 | savedInstanceState: Bundle? 28 | ): View? { 29 | binding = FragmentUsersBinding.inflate(inflater, container, false) 30 | return binding.root 31 | } 32 | 33 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 34 | super.onViewCreated(view, savedInstanceState) 35 | users_recyclerview.addOnItemClickListener(viewModel.onItemClickListener) 36 | } 37 | 38 | override fun onStart() { 39 | super.onStart() 40 | arguments?.let { bundle -> 41 | val args = UsersFragmentArgs.fromBundle(bundle) 42 | viewModel.get(args.parentId, args.requestId) 43 | .observe(this, Observer { 44 | binding.viewmodel = viewModel.setUsers(it) 45 | }) 46 | } 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/users/UsersViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.users 2 | 3 | import android.view.View 4 | import androidx.lifecycle.LiveData 5 | import androidx.lifecycle.ViewModel 6 | import androidx.navigation.findNavController 7 | import io.github.horaciocome1.reaque.data.subscriptions.SubscriptionsRepository 8 | import io.github.horaciocome1.reaque.data.topics.Topic 9 | import io.github.horaciocome1.reaque.data.users.User 10 | import io.github.horaciocome1.reaque.data.users.UsersRepository 11 | import io.github.horaciocome1.reaque.util.Constants 12 | 13 | class UsersViewModel( 14 | private val usersRepository: UsersRepository, 15 | private val subscriptionsRepository: SubscriptionsRepository 16 | ) : ViewModel() { 17 | 18 | var users: List = mutableListOf() 19 | 20 | val onItemClickListener: (View, Int) -> Unit = { view, position -> 21 | if (users.isNotEmpty()) { 22 | val directions = UsersFragmentDirections.actionOpenUserProfileFromUsers(users[position].id) 23 | view.findNavController().navigate(directions) 24 | } 25 | } 26 | 27 | fun setUsers(users: List): UsersViewModel { 28 | this.users = users 29 | return this 30 | } 31 | 32 | fun get(parentId: String, requestId: String): LiveData> { 33 | return when (requestId) { 34 | Constants.SUBSCRIPTIONS_REQUEST -> subscriptionsRepository.getSubscriptions(User(parentId)) 35 | Constants.SUBSCRIBERS_REQUEST -> subscriptionsRepository.getSubscribers(User(parentId)) 36 | else -> usersRepository.get(Topic(parentId)) 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/users/UsersViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.users 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import io.github.horaciocome1.reaque.data.subscriptions.SubscriptionsRepository 6 | import io.github.horaciocome1.reaque.data.users.UsersRepository 7 | 8 | class UsersViewModelFactory( 9 | private val usersRepository: UsersRepository, 10 | private val subscriptionsRepository: SubscriptionsRepository 11 | ) : ViewModelProvider.NewInstanceFactory() { 12 | 13 | @Suppress("UNCHECKED_CAST") 14 | override fun create(modelClass: Class) = 15 | UsersViewModel(usersRepository, subscriptionsRepository) as T 16 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/users/profile/UserProfileViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.users.profile 2 | 3 | import android.view.View 4 | import androidx.lifecycle.ViewModel 5 | import androidx.navigation.findNavController 6 | import io.github.horaciocome1.reaque.data.subscriptions.SubscriptionsRepository 7 | import io.github.horaciocome1.reaque.data.users.User 8 | import io.github.horaciocome1.reaque.data.users.UsersRepository 9 | import io.github.horaciocome1.reaque.util.Constants 10 | 11 | class UserProfileViewModel( 12 | private val usersRepository: UsersRepository, 13 | private val subscriptionsRepository: SubscriptionsRepository 14 | ) : ViewModel() { 15 | 16 | fun get(user: User) = usersRepository.get(user) 17 | 18 | fun subscribe(view: View, user: User) { 19 | view.isEnabled = false 20 | subscriptionsRepository.subscribe(user) { 21 | view.visibility = View.GONE 22 | } 23 | } 24 | 25 | fun unSubscribe(view: View, user: User) { 26 | view.isEnabled = false 27 | subscriptionsRepository.unSubscribe(user) { 28 | view.visibility = View.GONE 29 | } 30 | } 31 | 32 | fun amSubscribedTo(user: User) = subscriptionsRepository.amSubscribedTo(user) 33 | 34 | fun openSubscribers(view: View, user: User) { 35 | if (user.subscribers.isNotBlank() && user.subscribers != "0") { 36 | val directions = UserProfileFragmentDirections 37 | .actionOpenUsersFromUserProfile(user.id, Constants.SUBSCRIBERS_REQUEST) 38 | view.findNavController() 39 | .navigate(directions) 40 | } 41 | } 42 | 43 | fun openSubscriptions(view: View, user: User) { 44 | if (user.subscriptions.isNotBlank() && user.subscriptions != "0") { 45 | val directions = UserProfileFragmentDirections 46 | .actionOpenUsersFromUserProfile(user.id, Constants.SUBSCRIPTIONS_REQUEST) 47 | view.findNavController() 48 | .navigate(directions) 49 | } 50 | } 51 | 52 | fun openPosts(view: View, user: User) { 53 | if (user.posts.isNotBlank() && user.posts != "0") { 54 | val directions = UserProfileFragmentDirections 55 | .actionOpenPostsFromUserProfile(user.id, Constants.USER_POSTS_REQUEST) 56 | view.findNavController() 57 | .navigate(directions) 58 | } 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/users/profile/UserProfileViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.users.profile 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import io.github.horaciocome1.reaque.data.subscriptions.SubscriptionsRepository 6 | import io.github.horaciocome1.reaque.data.users.UsersRepository 7 | 8 | class UserProfileViewModelFactory( 9 | private val usersRepository: UsersRepository, 10 | private val subscriptionsRepository: SubscriptionsRepository 11 | ) : ViewModelProvider.NewInstanceFactory() { 12 | 13 | @Suppress("UNCHECKED_CAST") 14 | override fun create(modelClass: Class) = 15 | UserProfileViewModel(usersRepository, subscriptionsRepository) as T 16 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/users/update/UpdateUserViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.users.update 2 | 3 | import android.view.View 4 | import androidx.databinding.Bindable 5 | import androidx.lifecycle.MutableLiveData 6 | import androidx.navigation.findNavController 7 | import io.github.horaciocome1.reaque.data.users.User 8 | import io.github.horaciocome1.reaque.data.users.UsersRepository 9 | import io.github.horaciocome1.reaque.util.ObservableViewModel 10 | 11 | class UpdateUserViewModel(private val repository: UsersRepository) : ObservableViewModel() { 12 | 13 | val user = User("") 14 | 15 | @Bindable 16 | val bio = MutableLiveData() 17 | 18 | @Bindable 19 | val address = MutableLiveData() 20 | 21 | var isUpdatingUser = false 22 | 23 | val isUserReady: Boolean 24 | get() { 25 | user.run { 26 | return bio.isNotBlank() 27 | && address.isNotBlank() 28 | && bio != "null" 29 | && address != "null" 30 | } 31 | } 32 | 33 | val navigateUp: (View) -> Unit = { 34 | it.findNavController() 35 | .navigateUp() 36 | } 37 | 38 | fun get(user: User) = repository.get(user) 39 | 40 | fun update(view: View): UpdateUserViewModel { 41 | isUpdatingUser = true 42 | repository.update(user) { 43 | navigateUp(view) 44 | } 45 | return this 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/ui/users/update/UpdateUserViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.ui.users.update 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import io.github.horaciocome1.reaque.data.users.UsersRepository 6 | 7 | class UpdateUserViewModelFactory(private val repository: UsersRepository) : 8 | ViewModelProvider.NewInstanceFactory() { 9 | 10 | @Suppress("UNCHECKED_CAST") 11 | override fun create(modelClass: Class) = 12 | UpdateUserViewModel(repository) as T 13 | 14 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/util/Constants.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.util 17 | 18 | object Constants { 19 | 20 | const val DEFAULT = 123456789 21 | 22 | // StartActivityForResult 23 | const val PICK_IMAGE_FROM_GALLERY_REQUEST_CODE = 1207 24 | const val GOOGLE_SIGN_IN_REQUEST_CODE = 1208 25 | const val STORAGE_PERMISSION_CODE = 1209 26 | 27 | // Glide 28 | const val CIRCLE = 2307 29 | const val BLUR = 2308 30 | 31 | // list type 32 | const val LISTING_TOPICS = 4401 33 | const val LISTING_POSTS = 4403 34 | const val LISTING_USERS = 4405 35 | 36 | // hosts 37 | const val FEED_FRAGMENT = 5501 38 | const val EXPLORE_FRAGMENT = 5502 39 | const val POSTS_FRAGMENT = 5503 40 | const val CREATE_POST_FRAGMENT = 5504 41 | const val USERS_FRAGMENT = 5505 42 | 43 | // strings 44 | const val LANDING_PAGE = "https://reaque.firebaseapp.com" 45 | const val BOOKMARKS_REQUEST = "bookmarks" 46 | const val SUBSCRIPTIONS_REQUEST = "subscriptions" 47 | const val SUBSCRIBERS_REQUEST = "subscribers" 48 | const val TOPIC_POSTS_REQUEST = "topic_posts" 49 | const val TOPIC_USERS_REQUEST = "topic_users" 50 | const val USER_POSTS_REQUEST = "user_posts" 51 | const val USER_ID = "USER_ID" 52 | const val MAIN_ACTIVITY = "MainActivity" 53 | 54 | object SharedPreferences { 55 | 56 | const val NAME = "SharedPreferencesPostDraft" 57 | const val POST_TITLE = "SharedPreferencesPostDraftPostTitle" 58 | const val POST_MESSAGE = "SharedPreferencesPostDraftPostMessage" 59 | 60 | } 61 | 62 | // 3 states boolean 63 | object States { 64 | const val TRUE = 1 65 | const val FALSE = 0 66 | const val UNDEFINED = -1 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/util/DateUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque.util 17 | 18 | import com.google.firebase.Timestamp 19 | import java.util.* 20 | 21 | val Timestamp.string: String 22 | get() { 23 | val calendar = Calendar.getInstance() 24 | calendar.time = toDate() 25 | return calendar.month + 26 | " ${calendar[Calendar.DAY_OF_MONTH]}," + 27 | " ${calendar[Calendar.YEAR]}" 28 | } 29 | 30 | val Calendar.month: String 31 | get() = when (this[Calendar.MONTH]) { 32 | Calendar.JANUARY -> "Janeiro" 33 | Calendar.FEBRUARY -> "Fevereiro" 34 | Calendar.MARCH -> "Março" 35 | Calendar.APRIL -> "Abril" 36 | Calendar.MAY -> "Maio" 37 | Calendar.JUNE -> "Junho" 38 | Calendar.JULY -> "Julho" 39 | Calendar.AUGUST -> "Agosto" 40 | Calendar.SEPTEMBER -> "Setembro" 41 | Calendar.OCTOBER -> "Outubro" 42 | Calendar.NOVEMBER -> "Novembro" 43 | Calendar.DECEMBER -> "Dezembro" 44 | else -> "month" 45 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/util/DomainUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations 14 | * under the License. 15 | */ 16 | 17 | package io.github.horaciocome1.reaque.util 18 | 19 | import com.google.firebase.auth.FirebaseUser 20 | import com.google.firebase.firestore.FieldValue 21 | import io.github.horaciocome1.reaque.data.posts.Post 22 | import io.github.horaciocome1.reaque.data.users.User 23 | 24 | val Post.map: Map 25 | get() = mapOf( 26 | "title" to title, 27 | "message" to message, 28 | "pic" to pic, 29 | "timestamp" to timestamp, 30 | "bookmarks" to 0, 31 | "readings" to 0, 32 | "rating" to 0, 33 | "shares" to 0, 34 | "score" to 0, 35 | "topic" to mapOf( 36 | "id" to topic.id, 37 | "title" to topic.title 38 | ), 39 | "user" to mapOf( 40 | "id" to user.id, 41 | "name" to user.name, 42 | "pic" to user.pic 43 | ) 44 | ) 45 | 46 | val Post.mapSimple: Map 47 | get() = mapOf( 48 | "id" to id, 49 | "title" to title, 50 | "pic" to pic, 51 | "timestamp" to timestamp, 52 | "topic" to mapOf( 53 | "id" to topic.id, 54 | "title" to topic.title 55 | ), 56 | "user" to mapOf( 57 | "id" to user.id, 58 | "name" to user.name, 59 | "pic" to user.pic 60 | ), 61 | "score" to score 62 | ) 63 | 64 | val User.map: Map 65 | get() = mapOf( 66 | "id" to id, 67 | "name" to name, 68 | "pic" to pic, 69 | "subscribers" to subscribers, 70 | "top_topic" to topTopic, 71 | "score" to score, 72 | "timestamp" to FieldValue.serverTimestamp() 73 | ) 74 | 75 | val User.mapSimple: Map 76 | get() = mapOf( 77 | "bio" to bio, 78 | "address" to address 79 | ) 80 | 81 | val FirebaseUser.user: User 82 | get() = User(uid).apply { 83 | name = displayName.toString() 84 | pic = photoUrl.toString() 85 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/util/DynamicLinksUtils.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.util 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import com.google.android.gms.tasks.Task 6 | import com.google.firebase.dynamiclinks.DynamicLink 7 | import com.google.firebase.dynamiclinks.FirebaseDynamicLinks 8 | import com.google.firebase.dynamiclinks.ShortDynamicLink 9 | import io.github.horaciocome1.reaque.data.posts.Post 10 | import io.github.horaciocome1.reaque.ui.MainActivity 11 | 12 | fun FirebaseDynamicLinks.buildShortDynamicLink( 13 | post: Post, 14 | onSuccessListener: (Intent) -> Unit 15 | ): Task { 16 | return createDynamicLink() 17 | .setLink(Uri.parse("${Constants.LANDING_PAGE}/${post.id}")) 18 | .setDomainUriPrefix("https://reaque.page.link") 19 | .setAndroidParameters( 20 | DynamicLink.AndroidParameters.Builder() 21 | .setFallbackUrl(Uri.parse(Constants.LANDING_PAGE)) 22 | .build() 23 | ) 24 | .setIosParameters( 25 | DynamicLink.IosParameters.Builder("") 26 | .setFallbackUrl(Uri.parse(Constants.LANDING_PAGE)) 27 | .setIpadFallbackUrl(Uri.parse(Constants.LANDING_PAGE)) 28 | .build() 29 | ) 30 | .setSocialMetaTagParameters( 31 | DynamicLink.SocialMetaTagParameters.Builder() 32 | .setTitle("${post.title} - ${post.user.name}") 33 | .setDescription(post.message) 34 | .setImageUrl(Uri.parse(post.pic)) 35 | .build() 36 | ) 37 | .buildShortDynamicLink() 38 | .addOnSuccessListener { 39 | val sendIntent = Intent().apply { 40 | action = Intent.ACTION_SEND 41 | putExtra(Intent.EXTRA_TEXT, it.shortLink.toString()) 42 | type = "text/plain" 43 | } 44 | val chooser = Intent.createChooser(sendIntent, post.title) 45 | onSuccessListener(chooser) 46 | } 47 | } 48 | 49 | fun MainActivity.handleDynamicLinks(onSuccessListener: (Post) -> Unit) { 50 | FirebaseDynamicLinks.getInstance() 51 | .getDynamicLink(intent) 52 | .addOnSuccessListener { 53 | it?.let { 54 | val postId: String = it.link 55 | .toString() 56 | .removePrefix("${Constants.LANDING_PAGE}/") 57 | val post = Post(postId) 58 | onSuccessListener(post) 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/util/ObservableViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.util 2 | 3 | import androidx.databinding.Observable 4 | import androidx.databinding.PropertyChangeRegistry 5 | import androidx.lifecycle.ViewModel 6 | 7 | open class ObservableViewModel: ViewModel(), Observable { 8 | 9 | private val callbacks: PropertyChangeRegistry by lazy { 10 | PropertyChangeRegistry() 11 | } 12 | 13 | override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) { 14 | callbacks.remove(callback) 15 | } 16 | 17 | override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) { 18 | callbacks.add(callback) 19 | } 20 | 21 | // notifies listeners that all properties of this instance have changed 22 | @Suppress("unused") 23 | fun notifyChange() = callbacks.notifyCallbacks(this, 0, null) 24 | 25 | // notifies listeners that a specific property has changed. 26 | // the getter for the property that changes should be marked with [@Bindable] 27 | // to generate a field in `BR` to be used as `fieldId` 28 | fun notifyPropertyChanged(fieldId: Int) = callbacks.notifyCallbacks(this, fieldId, null) 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/util/OnFocusChangeListener.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.util 2 | 3 | import android.content.Context 4 | import android.view.View 5 | import android.view.inputmethod.InputMethodManager 6 | import com.google.android.material.textfield.TextInputEditText 7 | 8 | class OnFocusChangeListener(private val context: Context?) : View.OnFocusChangeListener { 9 | 10 | override fun onFocusChange(view: View?, hasFocus: Boolean) { 11 | if (view is TextInputEditText && !hasFocus) { 12 | val service = context?.getSystemService(Context.INPUT_METHOD_SERVICE) 13 | if (service is InputMethodManager) 14 | service.hideSoftInputFromWindow(view.windowToken, 0) 15 | } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/horaciocome1/reaque/util/QuerySnapshotUtils.kt: -------------------------------------------------------------------------------- 1 | package io.github.horaciocome1.reaque.util 2 | 3 | import com.google.firebase.firestore.QuerySnapshot 4 | import io.github.horaciocome1.reaque.data.posts.Post 5 | import io.github.horaciocome1.reaque.data.topics.Topic 6 | import io.github.horaciocome1.reaque.data.users.User 7 | 8 | val QuerySnapshot.topics: MutableList 9 | get() { 10 | val list = mutableListOf() 11 | forEach { 12 | list.add(it.topic) 13 | } 14 | return list 15 | } 16 | 17 | val QuerySnapshot.users: MutableList 18 | get() { 19 | val list = mutableListOf() 20 | forEach { 21 | list.add(it.user) 22 | } 23 | return list 24 | } 25 | 26 | val QuerySnapshot.posts: MutableList 27 | get() { 28 | val list = mutableListOf() 29 | forEach { 30 | list.add(it.post) 31 | } 32 | return list 33 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 27 | 28 | 34 | 37 | 40 | 41 | 42 | 43 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_all_corners_rounded_secondary.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_bottomsheet.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_bottomsheet_stroke.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_shadow_bottom_to_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_bookmark_18.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/color_bottom_navigation.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/color_side_navigation.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_access_time_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_add_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_add_photo_alternate_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_arrow_forward_18.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_bookmark_border_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_bookmarks_18.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_close_24.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_cloud_download_18.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_drag_handle_24.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_edit_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_exit_to_app_18.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_explore_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_feedback_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_info_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_info_24.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_library_books_18.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_location_on_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_more_horiz_24.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_people_outline_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_share_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_short_text_18.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_subject_18.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_whatshot_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/font/roboto.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_light.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_medium.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_thin.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout-land/activity_main.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 24 | 25 | 28 | 29 | 35 | 36 | 44 | 45 | 46 | 47 | 56 | 57 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/fragment_explore.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 18 | 19 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/fragment_user_profile.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 20 | 21 | 29 | 30 | 35 | 36 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 59 | 60 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w600dp/layout_explore_topics_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 21 | 22 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w600dp/layout_feed_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w600dp/layout_posts_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w600dp/layout_users_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w900dp/layout_explore_topics_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 21 | 22 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w900dp/layout_feed_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w900dp/layout_posts_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w900dp/layout_users_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_create_post.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 18 | 19 | 22 | 23 | 28 | 29 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 64 | 65 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_explore.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 17 | 18 | 22 | 23 | 26 | 27 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 20 | 21 | 25 | 26 | 32 | 33 | 37 | 38 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_more.xml: -------------------------------------------------------------------------------- 1 | 15 | 17 | 18 | 19 | 20 | 23 | 24 | 27 | 28 | 29 | 30 | 35 | 36 | 40 | 41 | 47 | 48 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_posts.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 19 | 20 | 24 | 25 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_set_rating.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 29 | 30 | 47 | 48 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_update_user.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 15 | 16 | 17 | 18 | 24 | 25 | 33 | 34 | 42 | 43 | 44 | 45 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_user_profile.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 14 | 15 | 16 | 17 | 21 | 22 | 26 | 27 | 32 | 33 | 40 | 41 | 46 | 47 | 54 | 55 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_users.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 19 | 20 | 24 | 25 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_suggestion.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 19 | 20 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_topic.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 18 | 19 | 25 | 26 | 33 | 34 | 35 | 36 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_appbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_create_post_loading_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 19 | 20 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_explore_suggestions_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 21 | 22 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_explore_topics_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 21 | 22 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_feed_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_more_footer_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 24 | 25 | 29 | 30 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_more_session_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 16 | 17 | 37 | 38 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_posts_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_update_user_loading_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 19 | 20 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_users_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 19 | 20 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/menu/navigation.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 22 | 23 | 27 | 28 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-hdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-mdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | #ffffff 19 | #ffffff 20 | #7c4dff 21 | #b47cff 22 | #3f1dcb 23 | #ffffff 24 | #f44336 25 | 26 | 27 | #ff6d00 28 | #00c853 29 | #99000000 30 | 31 | #10000000 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/values-v21/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16dp 5 | 1dp 6 | 2dp 7 | 16dp 8 | 16dp 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | #fafafa 19 | #ffffff 20 | #7c4dff 21 | #b47cff 22 | #3f1dcb 23 | #000000 24 | #ffffff 25 | #F44336 26 | 27 | 28 | #ff6d00 29 | #00c853 30 | #99000000 31 | 32 | #50000000 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 0dp 19 | 1dp 20 | 2dp 21 | 16dp 22 | 16dp 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FAFAFA 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/preloaded_fonts.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | @font/roboto 20 | @font/roboto_light 21 | @font/roboto_medium 22 | @font/roboto_thin 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_descriptor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/test/java/io/github/horaciocome1/reaque/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package io.github.horaciocome1.reaque 17 | 18 | import org.junit.Assert.assertEquals 19 | import org.junit.Test 20 | 21 | /** 22 | * Example local unit test, which will execute on the development machine (host). 23 | * 24 | * See [testing documentation](http://d.android.com/tools/testing). 25 | */ 26 | class ExampleUnitTest { 27 | @Test 28 | fun addition_isCorrect() { 29 | assertEquals(4, 2 + 2) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 17 | 18 | buildscript { 19 | ext.kotlin_version = '1.3.50' 20 | ext.nav_version = '1.0.0' 21 | repositories { 22 | google() 23 | jcenter() 24 | maven { 25 | url 'https://maven.fabric.io/public' 26 | } 27 | } 28 | dependencies { 29 | classpath 'com.android.tools.build:gradle:3.5.0' 30 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 31 | classpath 'com.google.gms:google-services:4.3.1' 32 | classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:$nav_version" 33 | classpath 'com.google.firebase:perf-plugin:1.3.1' 34 | classpath 'io.fabric.tools:gradle:1.28.0' 35 | 36 | // NOTE: Do not place your application dependencies here; they belong 37 | // in the individual module build.gradle files 38 | } 39 | } 40 | 41 | allprojects { 42 | repositories { 43 | google() 44 | jcenter() 45 | maven { 46 | url 'https://jitpack.io' 47 | } 48 | } 49 | } 50 | 51 | task clean(type: Delete) { 52 | delete rootProject.buildDir 53 | } -------------------------------------------------------------------------------- /docs/DONATE.md: -------------------------------------------------------------------------------- 1 | # Donate 2 | Welcome, and it is my pleasure to see you here. 3 | If you want to help me as a developer, [please read this](https://github.com/horaciocome1/reaque/tree/polishing-foreground-and-background#for-developers-only-2) 4 | 5 | ## Financial support 6 | This is am open source project and is mainly maintained by donations. There are several channels in which you may achieve this. 7 | 8 | ### Mpesa 9 | You can donate using [Vodacom Mpesa](https://www.vm.co.mz/en/M-Pesa2) by sending your donation to _**84 384 5597**_. 10 | 11 | Thank you! -------------------------------------------------------------------------------- /docs/diagrams/reaque-architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/docs/diagrams/reaque-architecture.jpg -------------------------------------------------------------------------------- /docs/diagrams/use_case.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/docs/diagrams/use_case.png -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 Hor�cio Fl�vio Com� J�nior 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and limitations under the License. 14 | # 15 | org.gradle.jvmargs=-Xmx1536m 16 | 17 | # SPEED UP GRADLE 18 | #org.gradle.jvmargs=-Xmx3072m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 19 | 20 | # When configured, Gradle will run in incubating parallel mode. 21 | # This option should only be used with decoupled projects. More details, visit 22 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 23 | 24 | # SPEED UP GRADLE 25 | #org.gradle.parallel=true 26 | 27 | # Kotlin code style for this project: "official" or "obsolete": 28 | kotlin.code.style=official 29 | 30 | # androidx 31 | android.useAndroidX=true 32 | android.enableJetifier=true 33 | 34 | # code shrinker 35 | android.enableR8=true 36 | 37 | # databinding 38 | android.databinding.incremental=true 39 | 40 | # Enable the incremental annotation processing experimental flag SPEED UP GRADLE 41 | kapt.incremental.apt=true 42 | # SPEED UP GRADLE 43 | #org.gradle.configureondemand=true 44 | #-Pandroid.debug.obsoleteApi=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Aug 27 15:11:09 CAT 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /screenshots/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/logo.png -------------------------------------------------------------------------------- /screenshots/mock1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/mock1.png -------------------------------------------------------------------------------- /screenshots/mock2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/mock2.png -------------------------------------------------------------------------------- /screenshots/mock3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/mock3.png -------------------------------------------------------------------------------- /screenshots/screen1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/screen1.png -------------------------------------------------------------------------------- /screenshots/screen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/screen2.png -------------------------------------------------------------------------------- /screenshots/screen3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/screen3.png -------------------------------------------------------------------------------- /screenshots/screen4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/screen4.png -------------------------------------------------------------------------------- /screenshots/screen5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/screen5.png -------------------------------------------------------------------------------- /screenshots/screen6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/screen6.png -------------------------------------------------------------------------------- /screenshots/screen7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/screen7.png -------------------------------------------------------------------------------- /screenshots/screen8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horaciocome1/reaque-android-app/6a2409e318805da4f89ddd5cebf9c0687c356e5f/screenshots/screen8.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Horácio Flávio Comé Júnior 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | include ':app' 17 | --------------------------------------------------------------------------------