├── .gitignore ├── .idea ├── .gitignore ├── appInsightsSettings.xml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── deploymentTargetDropDown.xml ├── deploymentTargetSelector.xml ├── gradle.xml ├── kotlinc.xml ├── migrations.xml ├── misc.xml ├── other.xml └── vcs.xml ├── Database ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── google │ │ └── android │ │ └── piyush │ │ └── database │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── google │ │ └── android │ │ └── piyush │ │ └── database │ │ ├── DopamineDatabase.kt │ │ ├── dao │ │ └── DopamineDao.kt │ │ ├── entities │ │ ├── EntityFavouritePlaylist.kt │ │ ├── EntityRecentVideos.kt │ │ └── EntityVideoSearch.kt │ │ ├── model │ │ ├── CustomPlaylistView.kt │ │ └── CustomPlaylists.kt │ │ ├── repository │ │ └── DopamineDatabaseRepository.kt │ │ └── viewModel │ │ └── DatabaseViewModel.kt │ └── test │ └── java │ └── com │ └── google │ └── android │ └── piyush │ └── database │ └── ExampleUnitTest.kt ├── README.md ├── Youtube ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── google │ │ └── android │ │ └── piyush │ │ └── youtube │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── google │ │ └── android │ │ └── piyush │ │ └── youtube │ │ ├── model │ │ ├── ContentDetails.kt │ │ ├── Item.kt │ │ ├── SearchTube.kt │ │ ├── SearchTubeItems.kt │ │ ├── Shorts.kt │ │ ├── Snippet.kt │ │ ├── Youtube.kt │ │ ├── channelDetails │ │ │ └── YoutubeChannel.kt │ │ └── channelPlaylists │ │ │ └── ChannelPlaylists.kt │ │ ├── repository │ │ ├── YoutubeRepository.kt │ │ └── YoutubeRepositoryImpl.kt │ │ ├── utilities │ │ ├── YoutubeClient.kt │ │ └── YoutubeResource.kt │ │ └── viewModels │ │ ├── HomeViewModel.kt │ │ ├── LibraryViewModel.kt │ │ └── ShortsViewModel.kt │ └── test │ └── java │ └── com │ └── google │ └── android │ └── piyush │ └── youtube │ └── ExampleUnitTest.kt ├── app ├── .gitignore ├── 1.jpeg ├── 10.jpg ├── 11.jpg ├── 12.jpg ├── 13.jpg ├── 14.jpg ├── 15.jpg ├── 16.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 6.jpg ├── 7.jpg ├── 8.jpg ├── 9.jpg ├── build.gradle.kts ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── google │ │ └── android │ │ └── piyush │ │ └── dopamine │ │ └── ExampleInstrumentedTest.kt │ ├── google-services.json │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── android │ │ │ └── piyush │ │ │ └── dopamine │ │ │ ├── DopamineApp.kt │ │ │ ├── activities │ │ │ ├── AboutDeveloper.kt │ │ │ ├── AboutDopamine.kt │ │ │ ├── AboutUs.kt │ │ │ ├── CVPlaylist.kt │ │ │ ├── DopamineHome.kt │ │ │ ├── DopamineUserProfile.kt │ │ │ ├── DopamineVideoWatchHistory.kt │ │ │ ├── MainActivity.kt │ │ │ ├── YoutubeChannel.kt │ │ │ ├── YoutubeChannelPlaylistsVideos.kt │ │ │ └── YoutubePlayer.kt │ │ │ ├── adapters │ │ │ ├── CustomPlayListVAdapter.kt │ │ │ ├── CustomPlaylistsAdapter.kt │ │ │ ├── CustomPlaylistsVDataAdapter.kt │ │ │ ├── HomeAdapter.kt │ │ │ ├── LibraryAdapter.kt │ │ │ ├── RecentVideosAdapter.kt │ │ │ ├── SearchAdapter.kt │ │ │ ├── SearchHistoryAdapter.kt │ │ │ ├── ShortsAdapter.kt │ │ │ ├── YourFavouriteVideosAdapter.kt │ │ │ ├── YoutubeChannelPlaylistsAdapter.kt │ │ │ └── YoutubePlaylistsVideosAdapter.kt │ │ │ ├── authentication │ │ │ ├── User.kt │ │ │ ├── repository │ │ │ │ └── UserAuthRepositoryImpl.kt │ │ │ ├── utilities │ │ │ │ └── AuthUtility.kt │ │ │ └── viewModel │ │ │ │ └── UserAuthViewModel.kt │ │ │ ├── beta │ │ │ └── DopamineApp.kt │ │ │ ├── fragments │ │ │ ├── Home.kt │ │ │ ├── Library.kt │ │ │ ├── Search.kt │ │ │ └── Shorts.kt │ │ │ ├── utilities │ │ │ └── DopamineUtilities.kt │ │ │ ├── viewHolders │ │ │ ├── CustomPlayListVHolder.kt │ │ │ ├── CustomPlaylistsVDataHolder.kt │ │ │ ├── CustomPlaylistsViewHolder.kt │ │ │ ├── HomeViewHolder.kt │ │ │ ├── LibraryViewHolder.kt │ │ │ ├── RecentVideosViewHolder.kt │ │ │ ├── SearchHistoryViewHolder.kt │ │ │ ├── SearchViewHolder.kt │ │ │ ├── ShortsViewHolder.kt │ │ │ ├── YourFavouriteVideosViewHolder.kt │ │ │ ├── YoutubeChannelPlaylistsViewHolder.kt │ │ │ └── YoutubePlaylistsVideosViewHolder.kt │ │ │ └── viewModels │ │ │ ├── DopamineHomeViewModel.kt │ │ │ ├── SearchViewModel.kt │ │ │ ├── SharedViewModel.kt │ │ │ ├── YoutubeChannelPlaylistsVideosViewModel.kt │ │ │ ├── YoutubeChannelViewModel.kt │ │ │ └── YoutubePlayerViewModel.kt │ └── res │ │ ├── drawable │ │ ├── checked.xml │ │ ├── clear.xml │ │ ├── default_user.xml │ │ ├── done.xml │ │ ├── download_circle.xml │ │ ├── facebook.xml │ │ ├── get_data_problem.xml │ │ ├── github.xml │ │ ├── google_material_design_logo.xml │ │ ├── ic_add.xml │ │ ├── ic_alert.xml │ │ ├── ic_android.xml │ │ ├── ic_back.xml │ │ ├── ic_beta_app.xml │ │ ├── ic_copy_text.xml │ │ ├── ic_dialog_error.xml │ │ ├── ic_dopamine.xml │ │ ├── ic_download.xml │ │ ├── ic_facebook.xml │ │ ├── ic_favourite.xml │ │ ├── ic_favourite_videos_fill.xml │ │ ├── ic_favourite_videos_out.xml │ │ ├── ic_google.xml │ │ ├── ic_history.xml │ │ ├── ic_home.xml │ │ ├── ic_home_fill.xml │ │ ├── ic_home_out.xml │ │ ├── ic_info.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_library.xml │ │ ├── ic_library_fill.xml │ │ ├── ic_library_out.xml │ │ ├── ic_like_video.xml │ │ ├── ic_picture_in_picture.xml │ │ ├── ic_search.xml │ │ ├── ic_search_background.xml │ │ ├── ic_select.xml │ │ ├── ic_settings.xml │ │ ├── ic_shorts.xml │ │ ├── ic_shorts_fill.xml │ │ ├── ic_shorts_out.xml │ │ ├── ic_sign_out.xml │ │ ├── ic_theme.xml │ │ ├── ic_update.xml │ │ ├── ic_view.xml │ │ ├── ic_voice_search.xml │ │ ├── idcard.xml │ │ ├── instagram.xml │ │ ├── location.xml │ │ ├── mail.xml │ │ ├── mail_outline.xml │ │ ├── memory.xml │ │ ├── phone.xml │ │ ├── round_add_24.xml │ │ ├── round_download_24.xml │ │ ├── round_local_phone_24.xml │ │ ├── round_sd_storage_24.xml │ │ ├── share.xml │ │ ├── unchecked.xml │ │ ├── video.xml │ │ ├── website.xml │ │ ├── whatsapp.xml │ │ └── wifi_off.xml │ │ ├── font │ │ ├── circular_spotify.otf │ │ ├── circular_std.otf │ │ ├── gotham.ttf │ │ └── proxima_nova.otf │ │ ├── layout-land │ │ └── activity_main.xml │ │ ├── layout │ │ ├── activity_about_developer.xml │ │ ├── activity_about_dopamine.xml │ │ ├── activity_about_us.xml │ │ ├── activity_cvplaylist.xml │ │ ├── activity_dopamine_home.xml │ │ ├── activity_dopamine_user_profile.xml │ │ ├── activity_dopamine_video_watch_history.xml │ │ ├── activity_main.xml │ │ ├── activity_youtube_channel.xml │ │ ├── activity_youtube_channel_playlists_videos.xml │ │ ├── activity_youtube_player.xml │ │ ├── app_dopamine_image.xml │ │ ├── bottom_sheet_add_playlist.xml │ │ ├── bottom_sheet_add_to_a_playlist.xml │ │ ├── fragment_home.xml │ │ ├── fragment_library.xml │ │ ├── fragment_search.xml │ │ ├── fragment_shorts.xml │ │ ├── item_activity_video_views_history.xml │ │ ├── item_activity_youtube_channel_playlists.xml │ │ ├── item_activity_youtube_playlists_videos.xml │ │ ├── item_custom_dialog.xml │ │ ├── item_custom_playlists_view.xml │ │ ├── item_frag_cust_lst_view.xml │ │ ├── item_fragment_home.xml │ │ ├── item_fragment_library.xml │ │ ├── item_fragment_library_favorites_shimmer.xml │ │ ├── item_fragment_library_your_favourite_videos.xml │ │ ├── item_fragment_search.xml │ │ ├── item_fragment_search_videos.xml │ │ ├── item_fragment_shorts.xml │ │ ├── shimmer_item_fragment_home.xml │ │ ├── shimmer_item_fragment_library.xml │ │ └── shimmer_item_fragment_shorts.xml │ │ ├── menu │ │ ├── bottom_nav_menu.xml │ │ ├── search_menu.xml │ │ └── user_profile_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── raw │ │ └── auth.json │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ ├── data_extraction_rules.xml │ │ └── provider_paths.xml │ └── test │ └── java │ └── com │ └── google │ └── android │ └── piyush │ └── dopamine │ └── ExampleUnitTest.kt ├── build.gradle.kts ├── google-services.json ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── version.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/appInsightsSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 26 | 27 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/deploymentTargetSelector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/other.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Database/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /Database/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.library) 3 | alias(libs.plugins.jetbrains.kotlin.android) 4 | id("com.google.devtools.ksp") 5 | } 6 | 7 | android { 8 | namespace = "com.google.android.piyush.database" 9 | compileSdk = 34 10 | 11 | defaultConfig { 12 | minSdk = 24 13 | 14 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 15 | consumerProguardFiles("consumer-rules.pro") 16 | } 17 | 18 | buildTypes { 19 | release { 20 | isMinifyEnabled = false 21 | proguardFiles( 22 | getDefaultProguardFile("proguard-android-optimize.txt"), 23 | "proguard-rules.pro" 24 | ) 25 | } 26 | } 27 | compileOptions { 28 | sourceCompatibility = JavaVersion.VERSION_1_8 29 | targetCompatibility = JavaVersion.VERSION_1_8 30 | } 31 | kotlinOptions { 32 | jvmTarget = "1.8" 33 | } 34 | } 35 | 36 | dependencies { 37 | 38 | implementation(libs.androidx.core.ktx) 39 | implementation(libs.androidx.appcompat) 40 | implementation(libs.material) 41 | implementation(libs.androidx.room.ktx) 42 | implementation(libs.androidx.room.runtime) 43 | implementation(libs.firebase.auth.ktx) 44 | ksp(libs.androidx.room.compiler) 45 | implementation(libs.androidx.lifecycle.viewmodel.ktx) 46 | testImplementation(libs.junit) 47 | androidTestImplementation(libs.androidx.junit) 48 | androidTestImplementation(libs.androidx.espresso.core) 49 | } -------------------------------------------------------------------------------- /Database/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/Database/consumer-rules.pro -------------------------------------------------------------------------------- /Database/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 name 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 name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /Database/src/androidTest/java/com/google/android/piyush/database/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.google.android.piyush.database.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /Database/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Database/src/main/java/com/google/android/piyush/database/DopamineDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database 2 | 3 | import android.content.Context 4 | import androidx.room.Database 5 | import androidx.room.Room 6 | import androidx.room.RoomDatabase 7 | import com.google.android.piyush.database.dao.DopamineDao 8 | import com.google.android.piyush.database.entities.EntityFavouritePlaylist 9 | import com.google.android.piyush.database.entities.EntityRecentVideos 10 | import com.google.android.piyush.database.entities.EntityVideoSearch 11 | 12 | @Database(entities = [EntityVideoSearch::class, EntityRecentVideos::class,EntityFavouritePlaylist::class], version = 1, exportSchema = false) 13 | abstract class DopamineDatabase : RoomDatabase() { 14 | abstract fun dopamineDao(): DopamineDao 15 | companion object { 16 | @Volatile 17 | private var INSTANCE: DopamineDatabase? = null 18 | private const val DATABASE_NAME = "dopamine_database" 19 | 20 | fun getDatabase(context: Context): DopamineDatabase { 21 | return INSTANCE ?: synchronized(this) { 22 | val instance = Room.databaseBuilder( 23 | context.applicationContext, 24 | DopamineDatabase::class.java, 25 | DATABASE_NAME 26 | ).build() 27 | INSTANCE = instance 28 | instance 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Database/src/main/java/com/google/android/piyush/database/dao/DopamineDao.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Insert 5 | import androidx.room.Query 6 | import com.google.android.piyush.database.entities.EntityFavouritePlaylist 7 | import com.google.android.piyush.database.entities.EntityRecentVideos 8 | import com.google.android.piyush.database.entities.EntityVideoSearch 9 | 10 | @Dao 11 | interface DopamineDao { 12 | @Insert 13 | suspend fun insertSearchVideos(vararg searchVideo: EntityVideoSearch) 14 | @Query("SELECT * FROM search_table") 15 | suspend fun getSearchVideoList(): List 16 | @Query("DELETE FROM search_table") 17 | suspend fun deleteSearchVideoList() 18 | @Insert 19 | suspend fun insertFavouriteVideos(vararg favouriteVideo : EntityFavouritePlaylist) 20 | @Query("SELECT videoId FROM favorite_playlist WHERE videoId = :videoId") 21 | suspend fun isFavouriteVideo (videoId : String) : String 22 | 23 | @Query("DELETE FROM favorite_playlist WHERE videoId = :videoId") 24 | suspend fun deleteFavouriteVideo(videoId : String) 25 | @Query("Select * FROM favorite_playlist") 26 | suspend fun getFavouritePlayList(): List 27 | @Insert 28 | suspend fun insertRecentVideos(vararg fav: EntityRecentVideos) 29 | @Query("Select * FROM recent_videos") 30 | suspend fun getRecentVideos(): List 31 | @Query("SELECT videoId FROM recent_videos WHERE videoId = :videoId") 32 | suspend fun isRecentVideo(videoId : String) : String 33 | @Query("Update recent_videos SET timing = :time WHERE videoId = :videoId") 34 | suspend fun updateRecentVideo(videoId: String, time: String) 35 | @Query("DELETE FROM recent_videos") 36 | suspend fun deleteRecentVideo() 37 | 38 | } -------------------------------------------------------------------------------- /Database/src/main/java/com/google/android/piyush/database/entities/EntityFavouritePlaylist.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "favorite_playlist") 7 | data class EntityFavouritePlaylist ( 8 | @PrimaryKey val videoId: String, 9 | val title: String?, 10 | val thumbnail: String?, 11 | val channelTitle: String?, 12 | val channelId : String? = null 13 | ) -------------------------------------------------------------------------------- /Database/src/main/java/com/google/android/piyush/database/entities/EntityRecentVideos.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "recent_videos") 7 | data class EntityRecentVideos( 8 | @PrimaryKey val id : Int, 9 | val videoId: String?, 10 | val title: String?, 11 | val thumbnail: String?, 12 | val timing : String?, 13 | val channelId : String? = null, 14 | ) 15 | -------------------------------------------------------------------------------- /Database/src/main/java/com/google/android/piyush/database/entities/EntityVideoSearch.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | 7 | @Entity(tableName = "search_table") 8 | data class EntityVideoSearch( 9 | @PrimaryKey(autoGenerate = true) 10 | @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER) val id: Int, 11 | @ColumnInfo(name = "search", typeAffinity = ColumnInfo.TEXT) val search: String? 12 | ) -------------------------------------------------------------------------------- /Database/src/main/java/com/google/android/piyush/database/model/CustomPlaylistView.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database.model 2 | 3 | data class CustomPlaylistView( 4 | val playListName : String, 5 | val playListDescription : String 6 | ) 7 | -------------------------------------------------------------------------------- /Database/src/main/java/com/google/android/piyush/database/model/CustomPlaylists.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database.model 2 | 3 | data class CustomPlaylists ( 4 | val videoId: String, 5 | val title: String?, 6 | val thumbnail: String?, 7 | val channelId : String?, 8 | val publishedAt : String?, 9 | val viewCount : String?, 10 | val channelTitle : String?, 11 | val duration : String? 12 | ) -------------------------------------------------------------------------------- /Database/src/main/java/com/google/android/piyush/database/repository/DopamineDatabaseRepository.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database.repository 2 | 3 | import com.google.android.piyush.database.dao.DopamineDao 4 | import com.google.android.piyush.database.entities.EntityFavouritePlaylist 5 | import com.google.android.piyush.database.entities.EntityRecentVideos 6 | import com.google.android.piyush.database.entities.EntityVideoSearch 7 | 8 | class DopamineDatabaseRepository( 9 | private val dopamineDao: DopamineDao 10 | ) { 11 | suspend fun insertSearchVideos(vararg searchVideo: EntityVideoSearch) { 12 | dopamineDao.insertSearchVideos(*searchVideo) 13 | } 14 | 15 | suspend fun getSearchVideoList(): List { 16 | return dopamineDao.getSearchVideoList() 17 | } 18 | 19 | suspend fun deleteSearchVideoList() { 20 | dopamineDao.deleteSearchVideoList() 21 | } 22 | 23 | suspend fun insertFavouriteVideos(vararg favouriteVideo: EntityFavouritePlaylist) { 24 | dopamineDao.insertFavouriteVideos(*favouriteVideo) 25 | } 26 | 27 | suspend fun isFavouriteVideo(videoId: String): String { 28 | return dopamineDao.isFavouriteVideo(videoId) 29 | } 30 | 31 | suspend fun deleteFavouriteVideo(videoId: String) { 32 | dopamineDao.deleteFavouriteVideo(videoId) 33 | } 34 | 35 | suspend fun getFavouritePlayList(): List { 36 | return dopamineDao.getFavouritePlayList() 37 | } 38 | 39 | suspend fun insertRecentVideos(vararg recentVideos: EntityRecentVideos) { 40 | dopamineDao.insertRecentVideos(*recentVideos) 41 | } 42 | 43 | suspend fun getRecentVideos(): List { 44 | return dopamineDao.getRecentVideos() 45 | } 46 | 47 | suspend fun isRecentVideo(videoId: String): String { 48 | return dopamineDao.isRecentVideo(videoId) 49 | } 50 | 51 | suspend fun updateRecentVideo(videoId: String, time: String) { 52 | dopamineDao.updateRecentVideo(videoId, time) 53 | } 54 | suspend fun deleteRecentVideo() { 55 | dopamineDao.deleteRecentVideo() 56 | } 57 | } -------------------------------------------------------------------------------- /Database/src/test/java/com/google/android/piyush/database/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.database 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dopamine (YouTube Clone) 2 | 3 | Dopamine is a YouTube clone that aims to replicate the functionality and features of the popular video-sharing platform. 4 | 5 | ## Authors 6 | 🌊 [Rajat_Kevat](https://kotlindevs.github.io) 7 | 8 | ## Logo of the application 9 | ![Logo](https://raw.githubusercontent.com/kotlindevs/Dopamine/Stable/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp) 10 | 11 | ## App Screenshots 12 | 13 | Below are some screenshots of the Dopamine application showcasing its features and user interface: 14 | 15 | | Screenshot 1 | Screenshot 2 | Screenshot 3 | 16 | |-------------------|-------------------|-------------------| 17 | | ![Image1](https://github.com/Admin-573/kotlin/blob/master/1.jpg?raw=true) | ![Image2](https://github.com/Admin-573/kotlin/blob/master/2.jpg?raw=true) | ![Image3](https://github.com/Admin-573/kotlin/blob/master/3.jpg?raw=true) | 18 | 19 | | Screenshot 4 | Screenshot 5 | Screenshot 6 | 20 | |-------------------|-------------------|-------------------| 21 | | ![Image4](https://github.com/Admin-573/kotlin/blob/master/4.jpg?raw=true) | ![Image5](https://github.com/Admin-573/kotlin/blob/master/5.jpg?raw=true) | ![Image6](https://github.com/Admin-573/kotlin/blob/master/6.jpg?raw=true) | 22 | 23 | ## Support 24 | 25 | For support, email [kotlindevslife@gmail.com](mailto:kotlindevslife@gmail.com)! 26 | 27 | -------------------------------------------------------------------------------- /Youtube/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /Youtube/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.library) 3 | alias(libs.plugins.jetbrains.kotlin.android) 4 | kotlin("plugin.serialization") version "1.9.23" 5 | } 6 | 7 | android { 8 | namespace = "com.google.android.piyush.youtube" 9 | compileSdk = 34 10 | 11 | defaultConfig { 12 | minSdk = 24 13 | 14 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 15 | consumerProguardFiles("consumer-rules.pro") 16 | } 17 | 18 | buildTypes { 19 | release { 20 | isMinifyEnabled = false 21 | proguardFiles( 22 | getDefaultProguardFile("proguard-android-optimize.txt"), 23 | "proguard-rules.pro" 24 | ) 25 | } 26 | } 27 | compileOptions { 28 | sourceCompatibility = JavaVersion.VERSION_1_8 29 | targetCompatibility = JavaVersion.VERSION_1_8 30 | } 31 | kotlinOptions { 32 | jvmTarget = "1.8" 33 | } 34 | } 35 | 36 | dependencies { 37 | 38 | implementation(libs.androidx.core.ktx) 39 | implementation(libs.androidx.appcompat) 40 | implementation(libs.material) 41 | implementation(libs.ktor.client.core) 42 | implementation(libs.ktor.client.cio) 43 | implementation(libs.ktor.client.content.negotiation) 44 | implementation(libs.kotlinx.serialization.json) 45 | implementation(libs.ktor.serialization.kotlinx.json) 46 | implementation(libs.androidx.lifecycle.viewmodel.ktx) 47 | testImplementation(libs.junit) 48 | androidTestImplementation(libs.androidx.junit) 49 | androidTestImplementation(libs.androidx.espresso.core) 50 | } -------------------------------------------------------------------------------- /Youtube/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/Youtube/consumer-rules.pro -------------------------------------------------------------------------------- /Youtube/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 name 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 name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /Youtube/src/androidTest/java/com/google/android/piyush/youtube/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.google.android.piyush.youtube.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /Youtube/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/ContentDetails.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class ContentDetails( 7 | val duration: String? = null, 8 | val videoPublishedAt: String? = null, 9 | val videoId: String? = null 10 | ) 11 | -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/Item.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model 2 | 3 | import com.google.android.piyush.youtube.model.channelDetails.BrandingSettings 4 | import kotlinx.serialization.Serializable 5 | 6 | @Serializable 7 | data class Item( 8 | val contentDetails: ContentDetails? = null, 9 | val snippet: Snippet? = null, 10 | val id: String? = null, 11 | val kind: String? = null, 12 | val statistics: Statistics? = null, 13 | val brandingSettings: BrandingSettings? = null 14 | ) -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/SearchTube.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SearchTube( 7 | val regionCode: String? = null, 8 | val items: List? = null 9 | ) -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/SearchTubeItems.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SearchTubeItems( 7 | val contentDetails: ContentDetails? = null, 8 | val snippet: Snippet? = null, 9 | val id: Id? = null, 10 | val kind: String? = null, 11 | val statistics: Statistics? = null 12 | ) 13 | 14 | @Serializable 15 | data class Id( 16 | val kind: String? = null, 17 | val videoId: String? = null 18 | ) -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/Shorts.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class Shorts( 7 | val videoId: String? = null 8 | ) -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/Snippet.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class Snippet( 7 | val channelId: String? = null, 8 | val channelTitle: String? = null, 9 | val customUrl: String? = null, 10 | val thumbnails: Thumbnails? = null, 11 | val publishedAt: String? = null, 12 | val kind: String? = null, 13 | val description: String? = null, 14 | val tags: List? = null, 15 | val title: String? = null 16 | ) 17 | 18 | 19 | @Serializable 20 | data class Thumbnails( 21 | val default: Default? = null, 22 | val medium: Medium? = null, 23 | val high: High? = null, 24 | val standard: Standard? = null 25 | ) 26 | 27 | @Serializable 28 | data class Statistics( 29 | val viewCount: Int? = 0, 30 | val subscriberCount: Int? = 0, 31 | val likeCount: Int? = 0 32 | ) 33 | 34 | @Serializable 35 | data class Standard( 36 | val url: String? = null, 37 | ) 38 | 39 | @Serializable 40 | data class High( 41 | val url: String? = null, 42 | ) 43 | 44 | @Serializable 45 | data class Default( 46 | val url: String? = null, 47 | ) 48 | 49 | @Serializable 50 | data class Medium( 51 | val url: String? = null, 52 | ) -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/Youtube.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class Youtube( 7 | val regionCode: String? = null, 8 | val items: List? = null 9 | ) -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/channelDetails/YoutubeChannel.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model.channelDetails 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class YoutubeChannel( 7 | val items : List? = null 8 | ) 9 | 10 | @Serializable 11 | data class Item( 12 | val kind : String? = null, 13 | val id : String? = null, 14 | val snippet : Snippet? = null, 15 | val statistics : Statistics? = null, 16 | val brandingSettings : BrandingSettings? = null, 17 | ) 18 | 19 | 20 | @Serializable 21 | data class Snippet( 22 | val title : String? = null, 23 | val description : String? = null, 24 | val customUrl : String? = null, 25 | val publishedAt : String? = null, 26 | val thumbnails : Thumbnails? = null, 27 | val country : String? = null, 28 | ) 29 | 30 | @Serializable 31 | data class Thumbnails( 32 | val default : Default? = null, 33 | ) 34 | 35 | @Serializable 36 | data class Default( 37 | val url : String? = null, 38 | val width : Int? = null, 39 | val height : Int? = null 40 | ) 41 | 42 | @Serializable 43 | data class Statistics( 44 | val viewCount: String? = null, 45 | val subscriberCount: String? = null, 46 | val likeCount: String? = null 47 | ) 48 | 49 | @Serializable 50 | data class BrandingSettings( 51 | val image : Image? = null 52 | ) 53 | 54 | @Serializable 55 | data class Image( 56 | val bannerExternalUrl : String? = null 57 | ) 58 | -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/model/channelPlaylists/ChannelPlaylists.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.model.channelPlaylists 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class ChannelPlaylists( 7 | val nextPageToken: String? = null, 8 | val pageInfo: PageInfo? = null, 9 | val items: List? = null 10 | ) 11 | 12 | @Serializable 13 | data class Item( 14 | val id: String? = null, 15 | val snippet: Snippet? = null, 16 | val contentDetails: ContentDetails? = null 17 | ) 18 | 19 | @Serializable 20 | data class PageInfo( 21 | val totalResults: Int? = null, 22 | val resultsPerPage: Int? = null 23 | ) 24 | 25 | @Serializable 26 | data class Snippet( 27 | val publishedAt: String? = null, 28 | val channelId: String? = null, 29 | val title: String? = null, 30 | val description: String? = null, 31 | val thumbnails: Thumbnails? = null, 32 | val channelTitle: String? = null, 33 | ) 34 | 35 | @Serializable 36 | data class ContentDetails( 37 | val itemCount: Int? = null 38 | ) 39 | 40 | @Serializable 41 | data class Thumbnails( 42 | val default: Default? = null, 43 | val medium: Medium? = null, 44 | val high: High? = null 45 | ) 46 | 47 | @Serializable 48 | data class Default( 49 | val url: String? = null, 50 | val width: Int? = null, 51 | val height: Int? = null 52 | ) 53 | 54 | @Serializable 55 | data class Medium( 56 | val url: String? = null, 57 | val width: Int? = null, 58 | val height: Int? = null 59 | ) 60 | 61 | @Serializable 62 | data class High( 63 | val url: String? = null, 64 | val width: Int? = null, 65 | val height: Int? = null 66 | ) -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/repository/YoutubeRepository.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.repository 2 | 3 | import com.google.android.piyush.youtube.model.SearchTube 4 | import com.google.android.piyush.youtube.model.Shorts 5 | import com.google.android.piyush.youtube.model.Youtube 6 | import com.google.android.piyush.youtube.model.channelDetails.YoutubeChannel 7 | import com.google.android.piyush.youtube.model.channelPlaylists.ChannelPlaylists 8 | 9 | interface YoutubeRepository { 10 | suspend fun getHomeVideos() : Youtube 11 | suspend fun getLibraryVideos(playListId : String) : Youtube 12 | suspend fun getSearchVideos(query : String) : SearchTube 13 | suspend fun getYoutubeShorts() : List 14 | suspend fun getChannelDetails(channelId : String) : YoutubeChannel 15 | suspend fun getChannelsPlaylists(channelId : String) : ChannelPlaylists 16 | suspend fun getPlaylistVideos(playListId : String) : Youtube 17 | suspend fun getVideoDetails(videoId : String) : Youtube 18 | } -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/utilities/YoutubeResource.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.utilities 2 | 3 | sealed class YoutubeResource { 4 | 5 | data class Success( 6 | val data: T 7 | ) : YoutubeResource() 8 | 9 | data class Error( 10 | val exception: Exception 11 | ) : YoutubeResource() 12 | 13 | data object Loading : YoutubeResource() 14 | 15 | override fun toString(): String { 16 | return when(this){ 17 | is Success<*> -> "Success[data=$data]" 18 | is Error -> "Error[exception=$exception]" 19 | Loading -> "Loading" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Youtube/src/main/java/com/google/android/piyush/youtube/viewModels/ShortsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube.viewModels 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | import androidx.lifecycle.ViewModelProvider 7 | import androidx.lifecycle.viewModelScope 8 | import com.google.android.piyush.youtube.model.Shorts 9 | import com.google.android.piyush.youtube.repository.YoutubeRepositoryImpl 10 | import com.google.android.piyush.youtube.utilities.YoutubeResource 11 | import kotlinx.coroutines.launch 12 | 13 | class ShortsViewModel( 14 | private val youtubeRepositoryImpl: YoutubeRepositoryImpl 15 | ) : ViewModel() { 16 | 17 | private val _shorts : MutableLiveData>> = MutableLiveData() 18 | val shorts : LiveData>> = _shorts 19 | 20 | init { 21 | viewModelScope.launch { 22 | try { 23 | _shorts.postValue(YoutubeResource.Loading) 24 | val response = youtubeRepositoryImpl.getYoutubeShorts() 25 | if(response.isEmpty()){ 26 | _shorts.postValue( 27 | YoutubeResource.Error( 28 | Exception("No Shorts Found") 29 | ) 30 | ) 31 | }else{ 32 | _shorts.postValue(YoutubeResource.Success(response)) 33 | } 34 | }catch (e : Exception){ 35 | _shorts.postValue(YoutubeResource.Error(e)) 36 | } 37 | } 38 | } 39 | } 40 | 41 | class ShortsViewModelFactory( 42 | private val youtubeRepositoryImpl: YoutubeRepositoryImpl 43 | ) : ViewModelProvider.Factory{ 44 | override fun create(modelClass: Class): T { 45 | if(modelClass.isAssignableFrom(ShortsViewModel::class.java)){ 46 | @Suppress("UNCHECKED_CAST") 47 | return ShortsViewModel(youtubeRepositoryImpl) as T 48 | }else{ 49 | throw IllegalArgumentException("Unknown ViewModel class") 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Youtube/src/test/java/com/google/android/piyush/youtube/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.youtube 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/1.jpeg -------------------------------------------------------------------------------- /app/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/10.jpg -------------------------------------------------------------------------------- /app/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/11.jpg -------------------------------------------------------------------------------- /app/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/12.jpg -------------------------------------------------------------------------------- /app/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/13.jpg -------------------------------------------------------------------------------- /app/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/14.jpg -------------------------------------------------------------------------------- /app/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/15.jpg -------------------------------------------------------------------------------- /app/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/16.jpg -------------------------------------------------------------------------------- /app/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/2.jpg -------------------------------------------------------------------------------- /app/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/3.jpg -------------------------------------------------------------------------------- /app/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/4.jpg -------------------------------------------------------------------------------- /app/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/5.jpg -------------------------------------------------------------------------------- /app/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/6.jpg -------------------------------------------------------------------------------- /app/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/7.jpg -------------------------------------------------------------------------------- /app/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/8.jpg -------------------------------------------------------------------------------- /app/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/9.jpg -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.application) 3 | alias(libs.plugins.jetbrains.kotlin.android) 4 | alias(libs.plugins.google.gms.google.services) 5 | } 6 | 7 | android { 8 | namespace = "com.google.android.piyush.dopamine" 9 | compileSdk = 34 10 | 11 | defaultConfig { 12 | applicationId = "com.google.android.piyush.dopamine" 13 | minSdk = 24 14 | targetSdk = 34 15 | versionCode = 1 16 | versionName = "version dopamine_20240704_01.phone.stable.dynamic" 17 | 18 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 19 | } 20 | 21 | buildTypes { 22 | release { 23 | isMinifyEnabled = false 24 | proguardFiles( 25 | getDefaultProguardFile("proguard-android-optimize.txt"), 26 | "proguard-rules.pro" 27 | ) 28 | signingConfig = signingConfigs.getByName("debug") 29 | } 30 | } 31 | compileOptions { 32 | sourceCompatibility = JavaVersion.VERSION_17 33 | targetCompatibility = JavaVersion.VERSION_17 34 | } 35 | kotlinOptions { 36 | jvmTarget = "17" 37 | } 38 | buildFeatures { 39 | viewBinding = true 40 | } 41 | 42 | splits { 43 | abi { 44 | isEnable = true 45 | reset() 46 | include("x86", "x86_64", "armeabi-v7a", "arm64-v8a") 47 | isUniversalApk = true 48 | } 49 | } 50 | packagingOptions { 51 | jniLibs { 52 | useLegacyPackaging = true 53 | } 54 | } 55 | 56 | } 57 | 58 | dependencies { 59 | 60 | implementation(libs.androidx.core.ktx) 61 | implementation(libs.androidx.appcompat) 62 | implementation(libs.material) 63 | implementation(libs.androidx.activity) 64 | implementation(libs.androidx.constraintlayout) 65 | implementation(libs.firebase.auth) 66 | implementation(libs.play.services.auth) 67 | implementation(libs.androidx.legacy.support.v4) 68 | implementation(libs.androidx.lifecycle.livedata.ktx) 69 | implementation(libs.androidx.lifecycle.viewmodel.ktx) 70 | implementation(libs.androidx.fragment.ktx) 71 | implementation(libs.shimmer) 72 | implementation(libs.glide) 73 | implementation(libs.core) 74 | implementation(libs.lottie) 75 | implementation (libs.exomedia) 76 | implementation(project(":Youtube")) 77 | implementation(project(":Database")) 78 | implementation(libs.androidx.preference) 79 | testImplementation(libs.junit) 80 | androidTestImplementation(libs.androidx.junit) 81 | androidTestImplementation(libs.androidx.espresso.core) 82 | } -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "929480757734", 4 | "project_id": "kotlinprojects-cr7", 5 | "storage_bucket": "kotlinprojects-cr7.firebasestorage.app" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:929480757734:android:09164c78fc362b32388627", 11 | "android_client_info": { 12 | "package_name": "com.google.android.piyush.dopamine" 13 | } 14 | }, 15 | "oauth_client": [ 16 | { 17 | "client_id": "929480757734-du8f823uda1upcdpf0ptpsc9terih1bp.apps.googleusercontent.com", 18 | "client_type": 3 19 | } 20 | ], 21 | "api_key": [ 22 | { 23 | "current_key": "AIzaSyAB8bbHqixtjJtcIosMwaD6D3lcc_67rFM" 24 | } 25 | ], 26 | "services": { 27 | "appinvite_service": { 28 | "other_platform_oauth_client": [ 29 | { 30 | "client_id": "929480757734-du8f823uda1upcdpf0ptpsc9terih1bp.apps.googleusercontent.com", 31 | "client_type": 3 32 | } 33 | ] 34 | } 35 | } 36 | } 37 | ], 38 | "configuration_version": "1" 39 | } -------------------------------------------------------------------------------- /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 name 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 name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/google/android/piyush/dopamine/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.google.android.piyush.dopamine", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "929480757734", 4 | "project_id": "kotlinprojects-cr7", 5 | "storage_bucket": "kotlinprojects-cr7.firebasestorage.app" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:929480757734:android:09164c78fc362b32388627", 11 | "android_client_info": { 12 | "package_name": "com.google.android.piyush.dopamine" 13 | } 14 | }, 15 | "oauth_client": [ 16 | { 17 | "client_id": "929480757734-du8f823uda1upcdpf0ptpsc9terih1bp.apps.googleusercontent.com", 18 | "client_type": 3 19 | } 20 | ], 21 | "api_key": [ 22 | { 23 | "current_key": "AIzaSyAB8bbHqixtjJtcIosMwaD6D3lcc_67rFM" 24 | } 25 | ], 26 | "services": { 27 | "appinvite_service": { 28 | "other_platform_oauth_client": [ 29 | { 30 | "client_id": "929480757734-du8f823uda1upcdpf0ptpsc9terih1bp.apps.googleusercontent.com", 31 | "client_type": 3 32 | } 33 | ] 34 | } 35 | } 36 | } 37 | ], 38 | "configuration_version": "1" 39 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 28 | 31 | 34 | 37 | 40 | 43 | 48 | 51 | 54 | 57 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 72 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/DopamineApp.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine 2 | 3 | import android.app.Application 4 | import android.os.StrictMode 5 | import androidx.appcompat.app.AppCompatDelegate 6 | import com.google.android.material.color.DynamicColors 7 | import com.google.android.material.color.DynamicColorsOptions 8 | import com.google.android.piyush.dopamine.utilities.Utilities 9 | 10 | 11 | class DopamineApp : Application() { 12 | override fun onCreate() { 13 | super.onCreate() 14 | 15 | val policy = StrictMode.ThreadPolicy.Builder().permitAll().build() 16 | 17 | StrictMode.setThreadPolicy(policy) 18 | 19 | DynamicColors.applyToActivitiesIfAvailable( 20 | this, DynamicColorsOptions.Builder().build() 21 | ) 22 | 23 | val dopamineApp = applicationContext.getSharedPreferences("DopamineApp", MODE_PRIVATE) 24 | 25 | if(dopamineApp.getString("Theme", Utilities.LIGHT_MODE) == Utilities.LIGHT_MODE){ 26 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) 27 | }else if(dopamineApp.getString("Theme", Utilities.DARK_MODE) == Utilities.DARK_MODE){ 28 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) 29 | }else{ 30 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) 31 | } 32 | 33 | if(dopamineApp.getBoolean("ExperimentalUserColor", false)){ 34 | DynamicColors.applyToActivitiesIfAvailable(this) 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/activities/CVPlaylist.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.activities 2 | 3 | import android.content.ContentValues.TAG 4 | import android.os.Bundle 5 | import android.util.Log 6 | import androidx.activity.enableEdgeToEdge 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.core.view.ViewCompat 9 | import androidx.core.view.WindowInsetsCompat 10 | import com.google.android.piyush.database.viewModel.DatabaseViewModel 11 | import com.google.android.piyush.dopamine.R 12 | import com.google.android.piyush.dopamine.adapters.CustomPlaylistsVDataAdapter 13 | import com.google.android.piyush.dopamine.databinding.ActivityCvplaylistBinding 14 | 15 | class CVPlaylist : AppCompatActivity() { 16 | private lateinit var databaseViewModel: DatabaseViewModel 17 | private lateinit var binding : ActivityCvplaylistBinding 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | databaseViewModel = DatabaseViewModel(applicationContext) 21 | binding = ActivityCvplaylistBinding.inflate(layoutInflater) 22 | setContentView(binding.root) 23 | enableEdgeToEdge() 24 | ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> 25 | val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) 26 | v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) 27 | insets 28 | } 29 | 30 | val playlist = intent.getStringExtra("playlistName") 31 | if(playlist != null) { 32 | binding.materialTextView.text = playlist 33 | binding.customPlayListVideos.apply { 34 | setHasFixedSize(false) 35 | layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context) 36 | adapter = CustomPlaylistsVDataAdapter(databaseViewModel.getPlaylistData(playlist),context) 37 | } 38 | Log.d(TAG, " -> Activity : CVPlaylist || PlaylistData : $playlist") 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/activities/DopamineVideoWatchHistory.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.activities 2 | 3 | import android.content.ContentValues 4 | import android.os.Bundle 5 | import android.util.Log 6 | import androidx.activity.enableEdgeToEdge 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.core.view.ViewCompat 9 | import androidx.core.view.WindowInsetsCompat 10 | import com.google.android.material.snackbar.Snackbar 11 | import com.google.android.piyush.database.viewModel.DatabaseViewModel 12 | import com.google.android.piyush.dopamine.R 13 | import com.google.android.piyush.dopamine.adapters.RecentVideosAdapter 14 | import com.google.android.piyush.dopamine.databinding.ActivityDopamineVideoWatchHistoryBinding 15 | 16 | class DopamineVideoWatchHistory : AppCompatActivity() { 17 | 18 | private lateinit var binding: ActivityDopamineVideoWatchHistoryBinding 19 | private lateinit var databaseViewModel: DatabaseViewModel 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | 24 | binding = ActivityDopamineVideoWatchHistoryBinding.inflate(layoutInflater) 25 | databaseViewModel = DatabaseViewModel(context = applicationContext) 26 | setContentView(binding.root) 27 | 28 | enableEdgeToEdge() 29 | ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> 30 | val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) 31 | v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) 32 | insets 33 | } 34 | 35 | databaseViewModel.getRecentVideos() 36 | 37 | databaseViewModel.recentVideos.observe(this) { recentVideos -> 38 | binding.recyclerView.apply { 39 | setHasFixedSize(true) 40 | layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context) 41 | adapter = RecentVideosAdapter(context,recentVideos) 42 | } 43 | if(recentVideos.isNullOrEmpty()){ 44 | binding.recyclerView.visibility = android.view.View.GONE 45 | binding.clearWatchHistory.visibility = android.view.View.GONE 46 | binding.lottieAnimationView.apply { 47 | visibility = android.view.View.VISIBLE 48 | setAnimation(R.raw.auth) 49 | loop(true) 50 | } 51 | } 52 | Log.d(ContentValues.TAG, " -> Activity : DopamineVideoWatchHistory || recentVideos : $recentVideos") 53 | } 54 | 55 | binding.topAppBar.setNavigationOnClickListener{ 56 | finish() 57 | } 58 | 59 | binding.clearWatchHistory.setOnClickListener { 60 | databaseViewModel.deleteRecentVideo() 61 | Snackbar.make(binding.root, "Watch History Cleared", Snackbar.LENGTH_SHORT).show() 62 | binding.recyclerView.visibility = android.view.View.GONE 63 | binding.clearWatchHistory.visibility = android.view.View.GONE 64 | binding.lottieAnimationView.apply { 65 | visibility = android.view.View.VISIBLE 66 | setAnimation(R.raw.auth) 67 | @Suppress("DEPRECATION") 68 | loop(true) 69 | playAnimation() 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/adapters/CustomPlayListVAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.adapters 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.graphics.Color 6 | import android.util.Log 7 | import android.view.LayoutInflater 8 | import android.view.ViewGroup 9 | import androidx.recyclerview.widget.RecyclerView 10 | import com.google.android.piyush.database.model.CustomPlaylistView 11 | import com.google.android.piyush.dopamine.R 12 | import com.google.android.piyush.dopamine.activities.CVPlaylist 13 | import com.google.android.piyush.dopamine.viewHolders.CustomPlayListVHolder 14 | import kotlin.random.Random 15 | 16 | 17 | class CustomPlayListVAdapter( 18 | private val context: Context, 19 | private var playlists: List?, 20 | ) : RecyclerView.Adapter() { 21 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomPlayListVHolder { 22 | return CustomPlayListVHolder( 23 | LayoutInflater.from( 24 | parent.context 25 | ) 26 | .inflate( 27 | R.layout.item_frag_cust_lst_view, parent, false 28 | ) 29 | ) 30 | } 31 | 32 | override fun getItemCount(): Int { 33 | return playlists?.size!! 34 | } 35 | 36 | override fun onBindViewHolder(holder: CustomPlayListVHolder, position: Int) { 37 | val playlistName = playlists?.get(position)?.playListName.toString() 38 | val playlistDescription = playlists?.get(position)?.playListDescription 39 | 40 | Log.d("playlistName", playlistName) 41 | 42 | val getColor = Color.argb( 43 | 255, 44 | Random.nextInt(256), 45 | Random.nextInt(256), 46 | Random.nextInt(256) 47 | ) 48 | 49 | holder.image.background.setTint(getColor) 50 | 51 | holder.title1.text = getString(playlistName) 52 | holder.title.text = playlistName 53 | holder.description.text = playlistDescription 54 | holder.playlist.setOnClickListener { 55 | val intent = Intent(context, CVPlaylist::class.java) 56 | intent.putExtra("playlistName", playlistName) 57 | context.startActivity(intent) 58 | } 59 | } 60 | 61 | private fun getString(name: String): String { 62 | if(name.isEmpty()){ 63 | return "🧿" 64 | }else{ 65 | var initials = "" 66 | val nameParts = name.split(" ") 67 | for (i in 0 until minOf(nameParts.size, 2)) { 68 | initials += nameParts[i][0].uppercase() 69 | } 70 | return initials 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/adapters/LibraryAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.adapters 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.view.LayoutInflater 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.bumptech.glide.Glide 9 | import com.google.android.piyush.dopamine.R 10 | import com.google.android.piyush.dopamine.activities.YoutubePlayer 11 | import com.google.android.piyush.dopamine.viewHolders.LibraryViewHolder 12 | import com.google.android.piyush.youtube.model.Youtube 13 | 14 | class LibraryAdapter( 15 | private val context: Context, 16 | private var youtube: Youtube? 17 | ) : RecyclerView.Adapter() { 18 | 19 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LibraryViewHolder { 20 | return LibraryViewHolder( 21 | LayoutInflater 22 | .from(parent.context) 23 | .inflate(R.layout.item_fragment_library, parent, false) 24 | ) 25 | } 26 | 27 | override fun getItemCount(): Int { 28 | return youtube?.items?.size!! 29 | } 30 | 31 | override fun onBindViewHolder(holder: LibraryViewHolder, position: Int) { 32 | val videos = youtube?.items?.get(position) 33 | Glide.with(context) 34 | .load(videos?.snippet?.thumbnails?.standard?.url) 35 | .into(holder.image) 36 | holder.title.text = videos?.snippet?.title 37 | holder.subtitle.text = videos?.snippet?.publishedAt 38 | holder.video.setOnClickListener { 39 | context.startActivity( 40 | Intent(context, YoutubePlayer::class.java) 41 | .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 42 | .putExtra("videoId",videos?.contentDetails?.videoId) 43 | .putExtra("channelId",videos?.snippet?.channelId) 44 | ) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/adapters/RecentVideosAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.adapters 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.view.LayoutInflater 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.bumptech.glide.Glide 9 | import com.google.android.piyush.database.entities.EntityRecentVideos 10 | import com.google.android.piyush.dopamine.R 11 | import com.google.android.piyush.dopamine.activities.YoutubePlayer 12 | import com.google.android.piyush.dopamine.viewHolders.RecentVideosViewHolder 13 | 14 | class RecentVideosAdapter( 15 | private val context: Context, 16 | private val videos: List? 17 | ) : RecyclerView.Adapter() { 18 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecentVideosViewHolder { 19 | return RecentVideosViewHolder( 20 | LayoutInflater.from(parent.context) 21 | .inflate(R.layout.item_activity_video_views_history, parent, false) 22 | ) 23 | } 24 | 25 | override fun getItemCount(): Int { 26 | return videos?.size!! 27 | } 28 | 29 | override fun onBindViewHolder(holder: RecentVideosViewHolder, position: Int) { 30 | val recentVideo = videos?.get(position) 31 | holder.title.text = recentVideo?.title 32 | holder.customName.text = recentVideo?.timing 33 | Glide.with(context).load(recentVideo?.thumbnail).into(holder.image) 34 | holder.videoCard.setOnClickListener { 35 | context.startActivity( 36 | Intent(context, YoutubePlayer::class.java) 37 | .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 38 | .putExtra("videoId",recentVideo?.videoId) 39 | .putExtra("channelId",recentVideo?.channelId) 40 | ) 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/adapters/SearchHistoryAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.adapters 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.google.android.piyush.database.entities.EntityVideoSearch 7 | import com.google.android.piyush.dopamine.R 8 | import com.google.android.piyush.dopamine.viewHolders.SearchHistoryViewHolder 9 | 10 | class SearchHistoryAdapter( 11 | private val searchHistoryItem : List? 12 | ) : RecyclerView.Adapter() { 13 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchHistoryViewHolder { 14 | return SearchHistoryViewHolder( 15 | LayoutInflater 16 | .from(parent.context) 17 | .inflate(R.layout.item_fragment_search, parent, false) 18 | ) 19 | } 20 | 21 | override fun getItemCount(): Int { 22 | return searchHistoryItem?.size!! 23 | } 24 | 25 | override fun onBindViewHolder(holder: SearchHistoryViewHolder, position: Int) { 26 | holder.searchHistoryItem.text = searchHistoryItem?.get(position)?.search 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/adapters/ShortsAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.adapters 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.google.android.piyush.dopamine.R 7 | import com.google.android.piyush.dopamine.viewHolders.ShortsViewHolder 8 | import com.google.android.piyush.youtube.model.Shorts 9 | import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer 10 | import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.YouTubePlayerCallback 11 | import kotlin.random.Random 12 | 13 | class ShortsAdapter( 14 | private val shorts: List? 15 | ) : RecyclerView.Adapter(){ 16 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShortsViewHolder { 17 | return ShortsViewHolder( 18 | LayoutInflater 19 | .from(parent.context) 20 | .inflate(R.layout.item_fragment_shorts, parent, false) 21 | ) 22 | } 23 | 24 | override fun getItemCount(): Int { 25 | return shorts?.size!! 26 | } 27 | 28 | override fun onBindViewHolder(holder: ShortsViewHolder, position: Int) { 29 | var uniqueRandomPosition = Random.nextInt(0, shorts?.size!!) 30 | while (uniqueRandomPosition == position) { 31 | uniqueRandomPosition = Random.nextInt(0,shorts.size) 32 | } 33 | val short = shorts[uniqueRandomPosition].videoId 34 | holder.shortsPlayer.getYouTubePlayerWhenReady( 35 | object : YouTubePlayerCallback { 36 | override fun onYouTubePlayer(youTubePlayer: YouTubePlayer) { 37 | youTubePlayer.cueVideo(short!!, 1f) 38 | } 39 | } 40 | ) 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/adapters/YourFavouriteVideosAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.adapters 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.view.LayoutInflater 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.bumptech.glide.Glide 9 | import com.google.android.piyush.database.entities.EntityFavouritePlaylist 10 | import com.google.android.piyush.dopamine.R 11 | import com.google.android.piyush.dopamine.activities.YoutubePlayer 12 | import com.google.android.piyush.dopamine.viewHolders.YourFavouriteVideosViewHolder 13 | 14 | class YourFavouriteVideosAdapter( 15 | private val context: Context, 16 | private val videos: List? 17 | ) : RecyclerView.Adapter() { 18 | override fun onCreateViewHolder( 19 | parent: ViewGroup, 20 | viewType: Int 21 | ): YourFavouriteVideosViewHolder { 22 | return YourFavouriteVideosViewHolder( 23 | LayoutInflater.from( 24 | parent.context 25 | ).inflate(R.layout.item_fragment_library_your_favourite_videos, parent, false) 26 | ) 27 | } 28 | 29 | override fun getItemCount(): Int { 30 | return videos?.size!! 31 | } 32 | 33 | override fun onBindViewHolder(holder: YourFavouriteVideosViewHolder, position: Int) { 34 | val favouriteVideo = videos?.get(position) 35 | holder.title.text = favouriteVideo?.title 36 | holder.customName.text = favouriteVideo?.channelTitle 37 | Glide.with(context).load(favouriteVideo?.thumbnail).into(holder.image) 38 | holder.videoCard.setOnClickListener { 39 | context.startActivity( 40 | Intent(context, YoutubePlayer::class.java) 41 | .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 42 | .putExtra("videoId",favouriteVideo?.videoId) 43 | .putExtra("channelId",favouriteVideo?.channelId) 44 | ) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/adapters/YoutubeChannelPlaylistsAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.adapters 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.view.LayoutInflater 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.bumptech.glide.Glide 9 | import com.google.android.piyush.dopamine.R 10 | import com.google.android.piyush.dopamine.activities.YoutubeChannelPlaylistsVideos 11 | import com.google.android.piyush.dopamine.viewHolders.YoutubeChannelPlaylistsViewHolder 12 | import com.google.android.piyush.youtube.model.channelPlaylists.ChannelPlaylists 13 | 14 | class YoutubeChannelPlaylistsAdapter( 15 | private val context: Context, 16 | private val playlists: ChannelPlaylists? 17 | ) : RecyclerView.Adapter() { 18 | override fun onCreateViewHolder( 19 | parent: ViewGroup, 20 | viewType: Int 21 | ): YoutubeChannelPlaylistsViewHolder { 22 | return YoutubeChannelPlaylistsViewHolder( 23 | LayoutInflater.from(parent.context).inflate( 24 | R.layout.item_activity_youtube_channel_playlists, parent, false 25 | ) 26 | ) 27 | } 28 | 29 | override fun getItemCount(): Int { 30 | return playlists?.items?.size!! 31 | } 32 | 33 | override fun onBindViewHolder(holder: YoutubeChannelPlaylistsViewHolder, position: Int) { 34 | val playListData = playlists?.items?.get(position) 35 | val playlistImage = playListData?.snippet?.thumbnails?.default?.url 36 | val playlistTitle = playListData?.snippet?.title 37 | val playlistChannelTitle = playListData?.snippet?.channelTitle 38 | 39 | Glide.with(context).load(playlistImage).into(holder.playlistImage) 40 | 41 | holder.playlistTitle.text = playlistTitle 42 | holder.playlistChannelTitle.text = playlistChannelTitle 43 | holder.playlist.setOnClickListener { 44 | if (!playlists?.items.isNullOrEmpty()) { 45 | context.startActivity( 46 | Intent( 47 | context, YoutubeChannelPlaylistsVideos::class.java 48 | ).addFlags( 49 | Intent.FLAG_ACTIVITY_NEW_TASK 50 | ).putExtra( 51 | "playlistId", playListData?.id 52 | ) 53 | ) 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/adapters/YoutubePlaylistsVideosAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.adapters 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.view.LayoutInflater 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.bumptech.glide.Glide 9 | import com.google.android.piyush.dopamine.R 10 | import com.google.android.piyush.dopamine.activities.YoutubePlayer 11 | import com.google.android.piyush.dopamine.viewHolders.YoutubePlaylistsVideosViewHolder 12 | import com.google.android.piyush.youtube.model.Youtube 13 | 14 | class YoutubePlaylistsVideosAdapter( 15 | private val context: Context, 16 | private val playlistVideos: Youtube? 17 | ) : RecyclerView.Adapter() { 18 | override fun onCreateViewHolder( 19 | parent: ViewGroup, 20 | viewType: Int 21 | ): YoutubePlaylistsVideosViewHolder { 22 | return YoutubePlaylistsVideosViewHolder( 23 | LayoutInflater.from(parent.context).inflate( 24 | R.layout.item_activity_youtube_playlists_videos, parent, false 25 | ) 26 | ) 27 | } 28 | 29 | override fun getItemCount(): Int { 30 | return playlistVideos?.items?.size!! 31 | } 32 | 33 | override fun onBindViewHolder(holder: YoutubePlaylistsVideosViewHolder, position: Int) { 34 | val videos = playlistVideos?.items?.get(position) 35 | Glide.with(context) 36 | .load(videos?.snippet?.thumbnails?.high?.url) 37 | .into(holder.image) 38 | holder.text1.text = videos?.snippet?.title 39 | holder.text2.text = videos?.snippet?.publishedAt 40 | holder.video.setOnClickListener { 41 | if (videos != null) { 42 | context.startActivity( 43 | Intent( 44 | context, YoutubePlayer::class.java 45 | ).addFlags( 46 | Intent.FLAG_ACTIVITY_NEW_TASK 47 | ).putExtra( 48 | "videoId",videos.contentDetails?.videoId 49 | ).putExtra( 50 | "channelId",videos.snippet?.channelId 51 | ) 52 | ) 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/authentication/User.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.authentication 2 | 3 | data class SignInResult( 4 | val userData : User?, 5 | val errorMessage : String? 6 | ) 7 | 8 | data class User( 9 | val userId : String, 10 | val userName : String, 11 | val userEmail : String, 12 | val userImage : String? 13 | ) 14 | 15 | data class SignInState( 16 | val isSignInSuccessful : Boolean = false, 17 | val signInError : String? = null 18 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/authentication/utilities/AuthUtility.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.authentication.utilities 2 | 3 | sealed class GoogleAuth( 4 | val data : T? = null, 5 | val message : String? = null 6 | ) { 7 | class Success(data : T) : GoogleAuth(data) 8 | class Error(message: String?,data: T? = null) : GoogleAuth(data,message) 9 | class Loading(data: T? = null) : GoogleAuth(data) 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/authentication/viewModel/UserAuthViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.authentication.viewModel 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.google.android.piyush.dopamine.authentication.SignInResult 6 | import com.google.android.piyush.dopamine.authentication.SignInState 7 | import com.google.android.piyush.dopamine.authentication.repository.UserAuthRepositoryImpl 8 | import com.google.firebase.auth.FirebaseUser 9 | import kotlinx.coroutines.flow.MutableStateFlow 10 | import kotlinx.coroutines.flow.asStateFlow 11 | import kotlinx.coroutines.flow.update 12 | 13 | class UserAuthViewModel( 14 | private val userAuthRepositoryImpl: UserAuthRepositoryImpl 15 | ) : ViewModel() { 16 | 17 | private val _state : MutableStateFlow = MutableStateFlow( 18 | SignInState() 19 | ) 20 | val state = _state.asStateFlow() 21 | 22 | fun currentUser() : FirebaseUser? { 23 | return userAuthRepositoryImpl.currentUser() 24 | } 25 | 26 | fun onSignInResult(result : SignInResult) { 27 | _state.update { 28 | it.copy( 29 | isSignInSuccessful = result.userData != null, 30 | signInError = result.errorMessage 31 | ) 32 | } 33 | } 34 | 35 | fun resetSignInState() { 36 | _state.update { SignInState() } 37 | } 38 | } 39 | 40 | class UserAuthViewModelFactory( 41 | private val userAuthRepositoryImpl: UserAuthRepositoryImpl 42 | ) : ViewModelProvider.Factory{ 43 | override fun create(modelClass: Class): T { 44 | if(modelClass.isAssignableFrom(UserAuthViewModel::class.java)) { 45 | @Suppress("UNCHECKED_CAST") 46 | return UserAuthViewModel(userAuthRepositoryImpl) as T 47 | } else { 48 | throw IllegalArgumentException("Unknown ViewModel class") 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/beta/DopamineApp.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.beta 2 | 3 | import android.app.Application 4 | import android.content.ContentValues.TAG 5 | import android.graphics.Bitmap 6 | import android.graphics.BitmapFactory 7 | import android.util.Log 8 | import androidx.appcompat.app.AppCompatDelegate 9 | import com.google.android.material.color.DynamicColors 10 | import com.google.android.piyush.dopamine.utilities.Utilities 11 | import java.io.IOException 12 | import java.net.URL 13 | 14 | 15 | class DopamineApp : Application() { 16 | override fun onCreate() { 17 | super.onCreate() 18 | /* 19 | val policy = ThreadPolicy.Builder().permitAll().build() 20 | 21 | StrictMode.setThreadPolicy(policy) 22 | val image = getBitmapFromUrl(FirebaseAuth.getInstance().currentUser?.photoUrl.toString()) 23 | 24 | if(image != null) { 25 | DynamicColors.applyToActivitiesIfAvailable( 26 | this, DynamicColorsOptions.Builder().setContentBasedSource( 27 | image 28 | ).build() 29 | ) 30 | } */ 31 | 32 | val dopamineApp = applicationContext.getSharedPreferences("DopamineApp", MODE_PRIVATE) 33 | 34 | if(dopamineApp.getString("Theme", Utilities.LIGHT_MODE) == Utilities.LIGHT_MODE){ 35 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) 36 | }else if(dopamineApp.getString("Theme", Utilities.DARK_MODE) == Utilities.DARK_MODE){ 37 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) 38 | }else{ 39 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) 40 | } 41 | 42 | if(dopamineApp.getBoolean("ExperimentalUserColor", false).equals(true)){ 43 | DynamicColors.applyToActivitiesIfAvailable(this) 44 | } 45 | } 46 | 47 | 48 | private fun getBitmapFromUrl(imageUrl: String): Bitmap? { 49 | try { 50 | val url = URL(imageUrl) 51 | val inputStream = url.openStream() 52 | return BitmapFactory.decodeStream(inputStream) 53 | } catch (e: IOException) { 54 | Log.e(TAG, "Error downloading image", e) 55 | return null 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/fragments/Shorts.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.fragments 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.ViewModelProvider 9 | import com.google.android.piyush.dopamine.R 10 | import com.google.android.piyush.dopamine.adapters.ShortsAdapter 11 | import com.google.android.piyush.dopamine.databinding.FragmentShortsBinding 12 | import com.google.android.piyush.dopamine.utilities.NetworkUtilities 13 | import com.google.android.piyush.youtube.repository.YoutubeRepositoryImpl 14 | import com.google.android.piyush.youtube.utilities.YoutubeResource 15 | import com.google.android.piyush.youtube.viewModels.ShortsViewModel 16 | import com.google.android.piyush.youtube.viewModels.ShortsViewModelFactory 17 | 18 | class Shorts : Fragment() { 19 | 20 | private var shortsFragmentBinding: FragmentShortsBinding? = null 21 | private lateinit var youtubeRepositoryImpl: YoutubeRepositoryImpl 22 | private lateinit var shortsViewModel: ShortsViewModel 23 | private lateinit var shortsViewModelFactory: ShortsViewModelFactory 24 | 25 | override fun onCreateView( 26 | inflater: LayoutInflater, container: ViewGroup?, 27 | savedInstanceState: Bundle? 28 | ): View { 29 | return inflater.inflate(R.layout.fragment_shorts, container, false) 30 | } 31 | 32 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 33 | super.onViewCreated(view, savedInstanceState) 34 | 35 | val binding = FragmentShortsBinding.bind(view) 36 | shortsFragmentBinding = binding 37 | youtubeRepositoryImpl = YoutubeRepositoryImpl() 38 | shortsViewModelFactory = ShortsViewModelFactory(youtubeRepositoryImpl) 39 | shortsViewModel = ViewModelProvider(this, shortsViewModelFactory)[ShortsViewModel::class.java] 40 | 41 | if(NetworkUtilities.isNetworkAvailable(requireContext())){ 42 | shortsViewModel.shorts.observe(viewLifecycleOwner){ shorts -> 43 | when(shorts){ 44 | is YoutubeResource.Loading -> {} 45 | is YoutubeResource.Success -> { 46 | if(shorts.data.isEmpty()){ 47 | binding.playWithShortsEffect.apply { 48 | startShimmer() 49 | visibility = View.VISIBLE 50 | } 51 | }else{ 52 | binding.playWithShortsEffect.apply { 53 | stopShimmer() 54 | visibility = View.GONE 55 | } 56 | binding.playWithShorts.apply { 57 | adapter = ShortsAdapter( 58 | shorts.data 59 | ) 60 | } 61 | } 62 | } 63 | is YoutubeResource.Error -> { 64 | binding.playWithShortsEffect.apply { 65 | startShimmer() 66 | visibility = View.VISIBLE 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/CustomPlayListVHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.card.MaterialCardView 6 | import com.google.android.material.textview.MaterialTextView 7 | import com.google.android.piyush.dopamine.R 8 | 9 | class CustomPlayListVHolder ( 10 | itemView : View 11 | ) : RecyclerView.ViewHolder(itemView) { 12 | val image : MaterialCardView = itemView.findViewById(R.id.custom_playlist_image) 13 | val title1: MaterialTextView = itemView.findViewById(R.id.playlist_logo_name) 14 | val title: MaterialTextView = itemView.findViewById(R.id.playlist_name) 15 | val description: MaterialTextView = itemView.findViewById(R.id.playlist_description) 16 | val playlist: MaterialCardView = itemView.findViewById(R.id.playlist) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/CustomPlaylistsVDataHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.card.MaterialCardView 6 | import com.google.android.material.imageview.ShapeableImageView 7 | import com.google.android.material.textview.MaterialTextView 8 | import com.google.android.piyush.dopamine.R 9 | 10 | class CustomPlaylistsVDataHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 11 | val youTubePlayerView : ShapeableImageView = itemView.findViewById(R.id.youtube_player_view) 12 | val imageView : ShapeableImageView = itemView.findViewById(R.id.channel_image) 13 | val videoTitle : MaterialTextView = itemView.findViewById(R.id.video_title) 14 | val channelTitle : MaterialTextView = itemView.findViewById(R.id.channel_title) 15 | val videoDuration : MaterialTextView = itemView.findViewById(R.id.video_duration) 16 | val youTubePlayer : MaterialCardView = itemView.findViewById(R.id.video_card) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/CustomPlaylistsViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.checkbox.MaterialCheckBox 6 | import com.google.android.material.textview.MaterialTextView 7 | import com.google.android.piyush.dopamine.R 8 | 9 | class CustomPlaylistsViewHolder( 10 | itemView : View 11 | ) : RecyclerView.ViewHolder(itemView) { 12 | 13 | val title: MaterialTextView = itemView.findViewById(R.id.title) 14 | val description: MaterialTextView = itemView.findViewById(R.id.description) 15 | val selectedPlaylistItem : MaterialCheckBox = itemView.findViewById(R.id.selectedPlaylistItem) 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/HomeViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.card.MaterialCardView 6 | import com.google.android.material.imageview.ShapeableImageView 7 | import com.google.android.material.textview.MaterialTextView 8 | import com.google.android.piyush.dopamine.R 9 | 10 | class HomeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 11 | val youTubePlayerView : ShapeableImageView = itemView.findViewById(R.id.youtube_player_view) 12 | val imageView : ShapeableImageView = itemView.findViewById(R.id.channel_image) 13 | val videoTitle : MaterialTextView = itemView.findViewById(R.id.video_title) 14 | val channelTitle : MaterialTextView = itemView.findViewById(R.id.channel_title) 15 | val videoDuration : MaterialTextView = itemView.findViewById(R.id.video_duration) 16 | val youTubePlayer : MaterialCardView = itemView.findViewById(R.id.video_card) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/LibraryViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.card.MaterialCardView 6 | import com.google.android.material.imageview.ShapeableImageView 7 | import com.google.android.material.textview.MaterialTextView 8 | import com.google.android.piyush.dopamine.R 9 | 10 | class LibraryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 11 | 12 | val video : MaterialCardView = itemView.findViewById(R.id.video) 13 | val image : ShapeableImageView = itemView.findViewById(R.id.image) 14 | val title : MaterialTextView = itemView.findViewById(R.id.text1) 15 | val subtitle : MaterialTextView = itemView.findViewById(R.id.text2) 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/RecentVideosViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.card.MaterialCardView 6 | import com.google.android.material.imageview.ShapeableImageView 7 | import com.google.android.material.textview.MaterialTextView 8 | import com.google.android.piyush.dopamine.R 9 | 10 | class RecentVideosViewHolder( 11 | itemView: View 12 | ) : RecyclerView.ViewHolder(itemView) { 13 | val image : ShapeableImageView = itemView.findViewById(R.id.image) 14 | val title : MaterialTextView = itemView.findViewById(R.id.text) 15 | val customName : MaterialTextView = itemView.findViewById(R.id.text1) 16 | val videoCard : MaterialCardView = itemView.findViewById(R.id.video_card) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/SearchHistoryViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.textview.MaterialTextView 6 | import com.google.android.piyush.dopamine.R 7 | 8 | class SearchHistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 9 | val searchHistoryItem : MaterialTextView = itemView.findViewById(R.id.textView) 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/SearchViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.button.MaterialButton 6 | import com.google.android.material.card.MaterialCardView 7 | import com.google.android.material.imageview.ShapeableImageView 8 | import com.google.android.material.textview.MaterialTextView 9 | import com.google.android.piyush.dopamine.R 10 | 11 | class SearchViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 12 | 13 | var image : ShapeableImageView = itemView.findViewById(R.id.image) 14 | var text1 : MaterialTextView = itemView.findViewById(R.id.text1) 15 | var text2 : MaterialTextView = itemView.findViewById(R.id.text2) 16 | var video : MaterialCardView = itemView.findViewById(R.id.video) 17 | var channelview : MaterialButton = itemView.findViewById(R.id.ChannelView) 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/ShortsViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.piyush.dopamine.R 6 | import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView 7 | 8 | class ShortsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 9 | val shortsPlayer : YouTubePlayerView = itemView.findViewById(R.id.shortsPlayer) 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/YourFavouriteVideosViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.card.MaterialCardView 6 | import com.google.android.material.imageview.ShapeableImageView 7 | import com.google.android.material.textview.MaterialTextView 8 | import com.google.android.piyush.dopamine.R 9 | 10 | class YourFavouriteVideosViewHolder( 11 | itemView: View 12 | ) : RecyclerView.ViewHolder(itemView) { 13 | 14 | val image : ShapeableImageView = itemView.findViewById(R.id.image) 15 | val title : MaterialTextView = itemView.findViewById(R.id.text) 16 | val customName : MaterialTextView = itemView.findViewById(R.id.text1) 17 | val videoCard : MaterialCardView = itemView.findViewById(R.id.video_card) 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/YoutubeChannelPlaylistsViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import android.widget.ImageView 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.google.android.material.card.MaterialCardView 7 | import com.google.android.material.textview.MaterialTextView 8 | import com.google.android.piyush.dopamine.R 9 | 10 | class YoutubeChannelPlaylistsViewHolder( 11 | itemView: View 12 | ) : RecyclerView.ViewHolder(itemView) { 13 | 14 | var playlistImage : ImageView = itemView.findViewById(R.id.playlistImage) 15 | var playlistTitle : MaterialTextView = itemView.findViewById(R.id.playlistTitle) 16 | var playlistChannelTitle : MaterialTextView = itemView.findViewById(R.id.playlistChannelTitle) 17 | var playlist : MaterialCardView = itemView.findViewById(R.id.playlist) 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewHolders/YoutubePlaylistsVideosViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewHolders 2 | 3 | import android.view.View 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.card.MaterialCardView 6 | import com.google.android.material.imageview.ShapeableImageView 7 | import com.google.android.material.textview.MaterialTextView 8 | import com.google.android.piyush.dopamine.R 9 | 10 | class YoutubePlaylistsVideosViewHolder( 11 | itemView: View 12 | ) : RecyclerView.ViewHolder(itemView) { 13 | 14 | val image : ShapeableImageView = itemView.findViewById(R.id.image) 15 | val text1 : MaterialTextView = itemView.findViewById(R.id.text1) 16 | val text2 : MaterialTextView = itemView.findViewById(R.id.text2) 17 | val video : MaterialCardView = itemView.findViewById(R.id.video) 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewModels/DopamineHomeViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewModels 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | 6 | class DopamineHomeViewModel : ViewModel() { 7 | 8 | private val _selectedFragment : MutableLiveData = MutableLiveData() 9 | val selectedFragment : MutableLiveData = _selectedFragment 10 | 11 | fun setSelectedFragment(fragment : Int) { 12 | _selectedFragment.value = fragment 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewModels/SearchViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewModels 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import androidx.lifecycle.ViewModelProvider 6 | import androidx.lifecycle.viewModelScope 7 | import com.google.android.piyush.youtube.model.SearchTube 8 | import com.google.android.piyush.youtube.repository.YoutubeRepositoryImpl 9 | import com.google.android.piyush.youtube.utilities.YoutubeResource 10 | import kotlinx.coroutines.launch 11 | 12 | class SearchViewModel( 13 | private val youtubeRepositoryImpl: YoutubeRepositoryImpl 14 | ) : ViewModel() { 15 | 16 | private val _searchVideos : MutableLiveData> = MutableLiveData() 17 | val searchVideos : MutableLiveData> = _searchVideos 18 | 19 | private val _reGetSearchVideos : MutableLiveData> = MutableLiveData() 20 | val reGetSearchVideos : MutableLiveData> = _reGetSearchVideos 21 | 22 | fun searchVideos(query : String) { 23 | viewModelScope.launch { 24 | try { 25 | _searchVideos.postValue(YoutubeResource.Loading) 26 | val videos = youtubeRepositoryImpl.getSearchVideos(query) 27 | if(videos.items.isNullOrEmpty()){ 28 | _searchVideos.postValue( 29 | YoutubeResource.Error( 30 | Exception( 31 | "The request cannot be completed because you have exceeded your quota." 32 | ) 33 | ) 34 | ) 35 | } else { 36 | _searchVideos.postValue(YoutubeResource.Success(videos)) 37 | } 38 | } catch (e : Exception) { 39 | _searchVideos.postValue(YoutubeResource.Error(e)) 40 | } 41 | } 42 | } 43 | 44 | fun reSearchVideos(query : String) { 45 | viewModelScope.launch { 46 | try { 47 | _reGetSearchVideos.postValue(YoutubeResource.Loading) 48 | val videos = youtubeRepositoryImpl.reGetSearchVideos(query) 49 | if(videos.items.isNullOrEmpty()){ 50 | _reGetSearchVideos.postValue( 51 | YoutubeResource.Error( 52 | Exception( 53 | "The request cannot be completed because you have exceeded your quota." 54 | ) 55 | ) 56 | ) 57 | } else { 58 | _reGetSearchVideos.postValue(YoutubeResource.Success(videos)) 59 | } 60 | } catch (e : Exception) { 61 | _reGetSearchVideos.postValue(YoutubeResource.Error(e)) 62 | } 63 | } 64 | } 65 | } 66 | 67 | 68 | @Suppress("UNCHECKED_CAST") 69 | class SearchViewModelFactory( 70 | private val youtubeRepositoryImpl: YoutubeRepositoryImpl 71 | ) : ViewModelProvider.Factory { 72 | override fun create(modelClass: Class): T { 73 | if(modelClass.isAssignableFrom(SearchViewModel::class.java)) { 74 | return SearchViewModel(youtubeRepositoryImpl) as T 75 | } else { 76 | throw IllegalArgumentException("Unknown ViewModel class") 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewModels/SharedViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewModels 2 | 3 | import androidx.lifecycle.ViewModel 4 | 5 | class SharedViewModel : ViewModel() -------------------------------------------------------------------------------- /app/src/main/java/com/google/android/piyush/dopamine/viewModels/YoutubeChannelPlaylistsVideosViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine.viewModels 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import androidx.lifecycle.ViewModelProvider 6 | import androidx.lifecycle.viewModelScope 7 | import com.google.android.piyush.youtube.model.Youtube 8 | import com.google.android.piyush.youtube.repository.YoutubeRepositoryImpl 9 | import com.google.android.piyush.youtube.utilities.YoutubeResource 10 | import kotlinx.coroutines.launch 11 | 12 | class YoutubeChannelPlaylistsVideosViewModel( 13 | private val youtubeRepositoryImpl: YoutubeRepositoryImpl 14 | ) : ViewModel() { 15 | 16 | private val _playlistsVideos : MutableLiveData> = MutableLiveData() 17 | val playlistsVideos : MutableLiveData> = _playlistsVideos 18 | 19 | fun getPlaylistsVideos(channelId: String) { 20 | viewModelScope.launch { 21 | try { 22 | _playlistsVideos.postValue(YoutubeResource.Loading) 23 | val response = youtubeRepositoryImpl.getPlaylistVideos(channelId) 24 | if(response.items.isNullOrEmpty()) { 25 | _playlistsVideos.postValue( 26 | YoutubeResource.Error( 27 | Exception( 28 | "The request cannot be completed because you have exceeded your quota." 29 | ) 30 | ) 31 | ) 32 | } else { 33 | _playlistsVideos.postValue( 34 | YoutubeResource.Success(response) 35 | ) 36 | } 37 | }catch (exception: Exception) { 38 | _playlistsVideos.postValue( 39 | YoutubeResource.Error(exception) 40 | ) 41 | } 42 | } 43 | } 44 | } 45 | 46 | @Suppress("UNCHECKED_CAST") 47 | class YoutubeChannelPlaylistsViewModelFactory( 48 | private val youtubeRepositoryImpl: YoutubeRepositoryImpl 49 | ) : ViewModelProvider.Factory { 50 | override fun create(modelClass: Class): T { 51 | if(modelClass.isAssignableFrom(YoutubeChannelPlaylistsVideosViewModel::class.java)) { 52 | return YoutubeChannelPlaylistsVideosViewModel(youtubeRepositoryImpl) as T 53 | } 54 | throw IllegalArgumentException("Unknown ViewModel class") 55 | } 56 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/checked.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/clear.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/default_user.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/done.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/download_circle.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/facebook.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/get_data_problem.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/github.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/google_material_design_logo.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_alert.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_android.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_back.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_beta_app.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_copy_text.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dialog_error.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dopamine.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_download.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_facebook.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favourite.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favourite_videos_fill.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favourite_videos_out.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_google.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_history.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home_fill.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home_out.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_library.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_library_fill.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_library_out.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_like_video.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_picture_in_picture.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_select.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shorts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shorts_fill.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shorts_out.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sign_out.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_theme.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_update.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_view.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_voice_search.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/idcard.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/instagram.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/location.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/mail.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/mail_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/memory.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/phone.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_add_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_download_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_local_phone_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_sd_storage_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/share.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/unchecked.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/video.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/website.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/whatsapp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/wifi_off.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/font/circular_spotify.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/font/circular_spotify.otf -------------------------------------------------------------------------------- /app/src/main/res/font/circular_std.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/font/circular_std.otf -------------------------------------------------------------------------------- /app/src/main/res/font/gotham.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/font/gotham.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/proxima_nova.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/font/proxima_nova.otf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_cvplaylist.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 25 | 26 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_dopamine_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 19 | 20 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_dopamine_video_watch_history.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 18 | 19 | 22 | 23 | 31 | 32 | 33 | 34 | 35 | 36 | 46 | 47 | 56 | 57 | 62 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_youtube_channel_playlists_videos.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 21 | 25 | 26 | 27 | 38 | 39 | 50 | 51 | 62 | 63 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_dopamine_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/bottom_sheet_add_playlist.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 22 | 23 | 24 | 32 | 33 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_shorts.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 15 | 16 | 17 | 18 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_activity_video_views_history.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 12 | 22 | 23 | 38 | 39 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_activity_youtube_channel_playlists.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 13 | 14 | 21 | 22 | 36 | 37 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_activity_youtube_playlists_videos.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 13 | 22 | 23 | 35 | 36 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_fragment_library.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 14 | 23 | 24 | 38 | 39 | 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_fragment_library_your_favourite_videos.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 12 | 22 | 23 | 38 | 39 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_fragment_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_fragment_shorts.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/shimmer_item_fragment_shorts.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/menu/bottom_nav_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 12 | 13 | 17 | 18 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/search_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/menu/user_profile_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 33 | 34 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Reply 5 | Reply to all 6 | 7 | 8 | 9 | reply 10 | reply_all 11 | 12 | 13 | 14 | Follow System Dark Mode 15 | Light Mode Selected 16 | Dark Mode Selected 17 | Auto Battery Dark Mode 18 | 19 | 20 | 21 | 1 22 | 2 23 | 3 24 | 4 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 34 | 35 | 39 | 40 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/xml/provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/test/java/com/google/android/piyush/dopamine/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.google.android.piyush.dopamine 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | alias(libs.plugins.android.application) apply false 4 | alias(libs.plugins.jetbrains.kotlin.android) apply false 5 | alias(libs.plugins.android.library) apply false 6 | alias(libs.plugins.google.gms.google.services) apply false 7 | kotlin("jvm") version "1.9.23" 8 | id("com.google.devtools.ksp") version "1.9.23-1.0.19" apply false 9 | } -------------------------------------------------------------------------------- /google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "11459978795", 4 | "project_id": "dopamine-rtx", 5 | "storage_bucket": "dopamine-rtx.firebasestorage.app" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:11459978795:android:f875a5d00554bbe3932c6e", 11 | "android_client_info": { 12 | "package_name": "com.google.android.piyush.dopamine" 13 | } 14 | }, 15 | "oauth_client": [], 16 | "api_key": [ 17 | { 18 | "current_key": "AIzaSyDHjTGfegLmCvNseHglpYhQoCFHH15MJ54" 19 | } 20 | ], 21 | "services": { 22 | "appinvite_service": { 23 | "other_platform_oauth_client": [] 24 | } 25 | } 26 | } 27 | ], 28 | "configuration_version": "1" 29 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. For more details, visit 12 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official 20 | # Enables namespacing of each library's R class so that its R class includes only the 21 | # resources declared in the library itself and none from the library's dependencies, 22 | # thereby reducing the size of the R class for that library 23 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlindevs/Dopamine/a4dd1e7b5f4a57215d6e4ec6e0482cb4fba31df2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 07 16:55:05 IST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google { 4 | content { 5 | includeGroupByRegex("com\\.android.*") 6 | includeGroupByRegex("com\\.google.*") 7 | includeGroupByRegex("androidx.*") 8 | } 9 | } 10 | mavenCentral() 11 | gradlePluginPortal() 12 | } 13 | } 14 | dependencyResolutionManagement { 15 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 16 | repositories { 17 | google() 18 | mavenCentral() 19 | maven(url = "https://jitpack.io") 20 | } 21 | } 22 | 23 | rootProject.name = "Dopamine" 24 | include(":app") 25 | include(":Youtube") 26 | include(":Database") 27 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "applicationId" : "com.google.android.piyush.dopamine", 3 | "minSdk" : 24, 4 | "targetsdk" : 34, 5 | "versionCode" : 1, 6 | "versionName" : "dopamine_20241503_04.phone.stable.dynamic", 7 | "jvmTarget" : 1.8, 8 | "url": "https://github.com/kotlindevs/Dopamine/releases/download/dopamine_20241503_04.phone.stable.dynamic/dopamine_20241503_04.phone.stable.dynamic-arm64-v8a-debug.apk", 9 | "inherit": true 10 | } --------------------------------------------------------------------------------