├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── raw │ │ │ │ └── map_style.json │ │ │ ├── drawable │ │ │ │ ├── profile.png │ │ │ │ ├── bg_gradient.xml │ │ │ │ ├── rounded_dialog.xml │ │ │ │ ├── image_rounded.xml │ │ │ │ ├── ic_message.xml │ │ │ │ ├── rounded_indicator.xml │ │ │ │ ├── ic_un_saved.xml │ │ │ │ ├── ic_play.xml │ │ │ │ ├── ic_pdf.xml │ │ │ │ ├── ic_theme.xml │ │ │ │ ├── ic_offline.xml │ │ │ │ ├── bg_decorator.xml │ │ │ │ ├── ic_menu_dots.xml │ │ │ │ ├── ic_menu_rate.xml │ │ │ │ ├── ic_menu_saved.xml │ │ │ │ ├── ic_menu_love_color.xml │ │ │ │ ├── ic_menu_love.xml │ │ │ │ ├── ic_menu_favorite_animation.xml │ │ │ │ ├── ic_linkedin.xml │ │ │ │ ├── ic_menu_profile_animation.xml │ │ │ │ ├── ic_menu_settings_animation.xml │ │ │ │ ├── ic_menu_portfolio_animation.xml │ │ │ │ ├── ic_saved.xml │ │ │ │ ├── ic_menu_experience_animation.xml │ │ │ │ ├── ic_youtube.xml │ │ │ │ ├── ic_menu_portfolio.xml │ │ │ │ ├── ic_play_store.xml │ │ │ │ ├── ic_duration.xml │ │ │ │ ├── ic_menu_top_favorite.xml │ │ │ │ ├── ic_menu_save.xml │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_twitter.xml │ │ │ │ ├── ic_menu_search.xml │ │ │ │ ├── ic_map.xml │ │ │ │ ├── ic_rate.xml │ │ │ │ ├── ic_menu_profile.xml │ │ │ │ ├── ic_github.xml │ │ │ │ ├── ic_link.xml │ │ │ │ ├── ic_empty.xml │ │ │ │ ├── ic_fab_profile.xml │ │ │ │ ├── ic_privacy.xml │ │ │ │ ├── ic_menu_privacy.xml │ │ │ │ ├── ic_read_more.xml │ │ │ │ ├── ic_wifi.xml │ │ │ │ ├── ic_menu_experience.xml │ │ │ │ ├── ic_avatar_placeholder.xml │ │ │ │ ├── ic_profile_placeholder.xml │ │ │ │ ├── ic_menu_refresh.xml │ │ │ │ ├── ic_launcher_foreground.xml │ │ │ │ ├── ic_globe.xml │ │ │ │ ├── ic_email.xml │ │ │ │ ├── ic_logo.xml │ │ │ │ ├── ic_menu_settings.xml │ │ │ │ ├── ic_category_code.xml │ │ │ │ ├── ic_no_connection.xml │ │ │ │ ├── ic_hand_waving.xml │ │ │ │ ├── ic_menu_share.xml │ │ │ │ ├── ic_category_structure.xml │ │ │ │ ├── ic_app_info_update.xml │ │ │ │ └── ic_category_web.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── values │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ ├── preloaded_fonts.xml │ │ │ │ ├── arrays.xml │ │ │ │ ├── attrs.xml │ │ │ │ └── dimens.xml │ │ │ ├── anim │ │ │ │ ├── slide_up.xml │ │ │ │ ├── slide_down.xml │ │ │ │ ├── fade_in.xml │ │ │ │ └── fade_out.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── color │ │ │ │ ├── side_navigation_icon_color.xml │ │ │ │ ├── side_navigation_text_color.xml │ │ │ │ ├── button_full_color.xml │ │ │ │ └── button_outline_icon_text_border_color.xml │ │ │ ├── font │ │ │ │ ├── questrial.xml │ │ │ │ └── roboto_thin.xml │ │ │ ├── layout │ │ │ │ ├── header_placeholder.xml │ │ │ │ ├── fragment_welcome.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── screen_profile_about.xml │ │ │ │ ├── fragment_experience.xml │ │ │ │ ├── preference_category_title.xml │ │ │ │ ├── preference_category_footer.xml │ │ │ │ ├── fragment_portfolio.xml │ │ │ │ ├── list_item_about.xml │ │ │ │ ├── list_item_screenshot.xml │ │ │ │ ├── list_item_about_header.xml │ │ │ │ └── preference_item_icon_title.xml │ │ │ ├── menu │ │ │ │ ├── favorite_list_menu.xml │ │ │ │ ├── portfolio_list_menu.xml │ │ │ │ ├── bottom_menu.xml │ │ │ │ ├── profile_menu.xml │ │ │ │ ├── side_menu.xml │ │ │ │ └── portfolio_detail_menu.xml │ │ │ └── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ ├── assets │ │ │ └── koin.properties │ │ ├── ic_launcher-web.png │ │ ├── java │ │ │ └── me │ │ │ │ └── tumur │ │ │ │ └── portfolio │ │ │ │ ├── utils │ │ │ │ ├── state │ │ │ │ │ ├── FavoriteState.kt │ │ │ │ │ ├── PreviewState.kt │ │ │ │ │ ├── ToastState.kt │ │ │ │ │ ├── NavigationState.kt │ │ │ │ │ └── ScreenState.kt │ │ │ │ ├── adapters │ │ │ │ │ └── listItemAdapters │ │ │ │ │ │ ├── portfolio │ │ │ │ │ │ ├── button │ │ │ │ │ │ │ ├── ButtonClickListener.kt │ │ │ │ │ │ │ ├── ButtonItem.kt │ │ │ │ │ │ │ ├── ButtonDiffCallBack.kt │ │ │ │ │ │ │ ├── ButtonNormalViewHolder.kt │ │ │ │ │ │ │ └── ButtonOutlineViewHolder.kt │ │ │ │ │ │ ├── PortfolioClickListener.kt │ │ │ │ │ │ ├── screenshot │ │ │ │ │ │ │ ├── ScreenShotClickListener.kt │ │ │ │ │ │ │ ├── ScreenShotDiffCallBack.kt │ │ │ │ │ │ │ ├── ScreenShotViewHolder.kt │ │ │ │ │ │ │ └── ScreenShotAdapter.kt │ │ │ │ │ │ ├── PortfolioDiffCallBack.kt │ │ │ │ │ │ ├── category │ │ │ │ │ │ │ ├── CategoryDiffCallBack.kt │ │ │ │ │ │ │ ├── CategoryViewHolder.kt │ │ │ │ │ │ │ └── CategoryAdapter.kt │ │ │ │ │ │ ├── PortfolioViewHolder.kt │ │ │ │ │ │ └── PortfolioAdapter.kt │ │ │ │ │ │ ├── social │ │ │ │ │ │ ├── SocialClickListener.kt │ │ │ │ │ │ ├── SocialDiffCallBack.kt │ │ │ │ │ │ ├── SocialViewHolder.kt │ │ │ │ │ │ └── SocialAdapter.kt │ │ │ │ │ │ ├── experience │ │ │ │ │ │ ├── ExperienceClickListener.kt │ │ │ │ │ │ ├── task │ │ │ │ │ │ │ ├── TaskDiffCallBack.kt │ │ │ │ │ │ │ ├── TaskViewHolder.kt │ │ │ │ │ │ │ └── TaskAdapter.kt │ │ │ │ │ │ ├── ExperienceDiffCallBack.kt │ │ │ │ │ │ ├── resource │ │ │ │ │ │ │ ├── ResourceDiffCallBack.kt │ │ │ │ │ │ │ ├── ResourceViewHolder.kt │ │ │ │ │ │ │ └── ResourceAdapter.kt │ │ │ │ │ │ ├── ExperienceViewHolder.kt │ │ │ │ │ │ └── ExperienceAdapter.kt │ │ │ │ │ │ ├── favorite │ │ │ │ │ │ ├── FavoriteClickListener.kt │ │ │ │ │ │ ├── FavoriteDiffCallBack.kt │ │ │ │ │ │ ├── FavoriteViewHolder.kt │ │ │ │ │ │ └── FavoriteAdapter.kt │ │ │ │ │ │ ├── about │ │ │ │ │ │ ├── AboutItem.kt │ │ │ │ │ │ ├── AboutDiffCallBack.kt │ │ │ │ │ │ ├── AboutItemViewHolder.kt │ │ │ │ │ │ └── AboutHeaderViewHolder.kt │ │ │ │ │ │ └── app │ │ │ │ │ │ ├── AppDiffCallBack.kt │ │ │ │ │ │ ├── AppViewHolder.kt │ │ │ │ │ │ └── AppAdapter.kt │ │ │ │ ├── extensions │ │ │ │ │ ├── Databinding.kt │ │ │ │ │ ├── ViewGroupExtensions.kt │ │ │ │ │ └── isNetworkAvailable.kt │ │ │ │ ├── constants │ │ │ │ │ └── BsConstants.kt │ │ │ │ ├── delegates │ │ │ │ │ └── Databinding.kt │ │ │ │ ├── toolbar │ │ │ │ │ └── CollapsibleToolbar.kt │ │ │ │ ├── theme │ │ │ │ │ └── ThemeHelper.kt │ │ │ │ └── fabButton │ │ │ │ │ └── ScrollAwareFabButton.kt │ │ │ │ ├── screens │ │ │ │ ├── portfolio │ │ │ │ │ └── detail │ │ │ │ │ │ ├── VideoClickListener.kt │ │ │ │ │ │ └── preview │ │ │ │ │ │ └── pager │ │ │ │ │ │ ├── PreviewPagerAdapter.kt │ │ │ │ │ │ └── PreviewPagerViewModel.kt │ │ │ │ ├── welcome │ │ │ │ │ └── pager │ │ │ │ │ │ ├── WelcomePagerAdapter.kt │ │ │ │ │ │ └── WelcomePagerViewModel.kt │ │ │ │ ├── settings │ │ │ │ │ └── dialog │ │ │ │ │ │ └── AppDialogViewModel.kt │ │ │ │ └── experience │ │ │ │ │ └── ExperienceViewModel.kt │ │ │ │ └── repository │ │ │ │ ├── network │ │ │ │ ├── Result.kt │ │ │ │ └── RestApi.kt │ │ │ │ ├── database │ │ │ │ ├── Converters.kt │ │ │ │ ├── dao │ │ │ │ │ ├── settings │ │ │ │ │ │ └── AppDao.kt │ │ │ │ │ ├── profile │ │ │ │ │ │ ├── AboutDao.kt │ │ │ │ │ │ ├── SocialDao.kt │ │ │ │ │ │ └── ProfileDao.kt │ │ │ │ │ ├── task │ │ │ │ │ │ └── TaskDao.kt │ │ │ │ │ ├── button │ │ │ │ │ │ └── ButtonDao.kt │ │ │ │ │ ├── location │ │ │ │ │ │ └── LocationDao.kt │ │ │ │ │ ├── category │ │ │ │ │ │ └── CategoryDao.kt │ │ │ │ │ ├── resource │ │ │ │ │ │ └── ResourceDao.kt │ │ │ │ │ ├── experience │ │ │ │ │ │ └── ExperienceDao.kt │ │ │ │ │ ├── screenshot │ │ │ │ │ │ └── ScreenShotDao.kt │ │ │ │ │ ├── welcome │ │ │ │ │ │ └── WelcomeDao.kt │ │ │ │ │ ├── portfolio │ │ │ │ │ │ └── PortfolioDao.kt │ │ │ │ │ └── favorite │ │ │ │ │ │ └── FavoriteDao.kt │ │ │ │ └── model │ │ │ │ │ ├── settings │ │ │ │ │ └── AppModel.kt │ │ │ │ │ ├── task │ │ │ │ │ └── TaskModel.kt │ │ │ │ │ ├── profile │ │ │ │ │ ├── AboutModel.kt │ │ │ │ │ ├── SocialModel.kt │ │ │ │ │ └── ProfileModel.kt │ │ │ │ │ ├── LocationModel.kt │ │ │ │ │ ├── welcome │ │ │ │ │ └── WelcomeModel.kt │ │ │ │ │ ├── screenshot │ │ │ │ │ └── ScreenShotModel.kt │ │ │ │ │ ├── button │ │ │ │ │ └── ButtonModel.kt │ │ │ │ │ ├── category │ │ │ │ │ └── CategoryModel.kt │ │ │ │ │ ├── resource │ │ │ │ │ └── ResourceModel.kt │ │ │ │ │ ├── favorite │ │ │ │ │ └── FavoriteModel.kt │ │ │ │ │ └── experience │ │ │ │ │ └── ExperienceModel.kt │ │ │ │ └── repo │ │ │ │ └── Repository.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── me │ │ │ └── tumur │ │ │ └── portfolio │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── me │ │ └── tumur │ │ └── portfolio │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── google-services.json ├── .idea ├── .gitignore ├── codeStyles │ └── codeStyleConfig.xml ├── encodings.xml ├── vcs.xml ├── kotlinc.xml ├── render.experimental.xml ├── dictionaries │ └── Tumur.xml ├── runConfigurations.xml ├── gradle.xml └── misc.xml ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── utils.gradle └── gradle.properties /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/src/main/res/raw/map_style.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name='Portfolio' 3 | -------------------------------------------------------------------------------- /app/src/main/assets/koin.properties: -------------------------------------------------------------------------------- 1 | URL=https://portfolio-app-147b5.web.app/ 2 | CONNECT=30 3 | READ=60 4 | WRITE=60 -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/drawable/profile.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtbdev/Android-Portfolio-App-2/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #9AA0A6 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/render.experimental.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/preloaded_fonts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @font/questrial 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/state/FavoriteState.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.state 2 | 3 | sealed class FavoriteState 4 | 5 | /** Empty */ 6 | object Empty : FavoriteState() 7 | 8 | /** Not Empty */ 9 | object NotEmpty : FavoriteState() -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/screens/portfolio/detail/VideoClickListener.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.screens.portfolio.detail 2 | 3 | class VideoClickListener(val clickListener: (url: String) -> Unit) { 4 | fun onClick(url: String) = clickListener(url) 5 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/network/Result.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.network 2 | 3 | sealed class Result 4 | 5 | /** Network request successful */ 6 | object Success : Result() 7 | 8 | /** Network request failed */ 9 | object Failed : Result() -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/state/PreviewState.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.state 2 | 3 | sealed class PreviewState 4 | 5 | /** Show progress bar */ 6 | object ProgressBar : PreviewState() 7 | 8 | /** Hide progress bar */ 9 | object PreviewImage : PreviewState() -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_up.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Sep 26 22:36:14 PDT 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_down.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/button/ButtonClickListener.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.button 2 | 3 | class ButtonClickListener(val clickListener: (url: String) -> Unit) { 4 | fun onClick(url: String) = clickListener(url) 5 | } -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rounded_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/network/RestApi.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.network 2 | 3 | import me.tumur.portfolio.repository.database.model.all.RequestAll 4 | import retrofit2.Response 5 | import retrofit2.http.GET 6 | 7 | interface RestApi { 8 | 9 | @GET("api/all/") 10 | suspend fun getAll(): Response 11 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/state/ToastState.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.state 2 | 3 | sealed class ToastState 4 | 5 | /** Saved */ 6 | object ToastSaved : ToastState() 7 | 8 | /** Unsaved */ 9 | object ToastUnsaved : ToastState() 10 | 11 | /** Show */ 12 | object ToastShow : ToastState() 13 | 14 | /** Showed */ 15 | object ToastEmpty : ToastState() -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/state/NavigationState.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.state 2 | 3 | sealed class NavigationState 4 | 5 | /** Hide Navigation */ 6 | object HideNavigation: NavigationState() 7 | 8 | /** Show Navigation */ 9 | object ShowNavigation : NavigationState() 10 | 11 | /** Hide Bottom navigation */ 12 | object GoneNavigation : NavigationState() -------------------------------------------------------------------------------- /app/src/main/res/color/side_navigation_icon_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/social/SocialClickListener.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.social 2 | 3 | import me.tumur.portfolio.repository.database.model.profile.SocialModel 4 | 5 | class SocialClickListener(val clickListener: (socialItem: SocialModel) -> Unit){ 6 | fun onClick(item: SocialModel) = clickListener(item) 7 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/extensions/Databinding.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.extensions 2 | 3 | import androidx.annotation.LayoutRes 4 | import androidx.databinding.ViewDataBinding 5 | import me.tumur.portfolio.utils.delegates.ActivityBindingProperty 6 | 7 | internal fun activityBinding(@LayoutRes resId: Int) = 8 | ActivityBindingProperty(resId) -------------------------------------------------------------------------------- /app/src/main/res/color/side_navigation_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/PortfolioClickListener.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio 2 | 3 | import me.tumur.portfolio.repository.database.model.portfolio.PortfolioModel 4 | 5 | class PortfolioClickListener(val clickListener: (item: PortfolioModel) -> Unit) { 6 | fun onClick(item: PortfolioModel) = clickListener(item) 7 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/ExperienceClickListener.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience 2 | 3 | import me.tumur.portfolio.repository.database.model.experience.ExperienceModel 4 | 5 | class ExperienceClickListener(val clickListener: (item: ExperienceModel) -> Unit) { 6 | fun onClick(item: ExperienceModel) = clickListener(item) 7 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_rounded.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/state/ScreenState.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.state 2 | 3 | sealed class ScreenState 4 | 5 | /** Splash Screen */ 6 | object SplashScreen: ScreenState() 7 | 8 | /** Welcome Screen */ 9 | object WelcomeScreen : ScreenState() 10 | 11 | /** Main Screen */ 12 | object MainScreen : ScreenState() 13 | 14 | /** Loader Screen */ 15 | object LoaderScreen : ScreenState() 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/font/questrial.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/header_placeholder.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/favorite/FavoriteClickListener.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.favorite 2 | 3 | import me.tumur.portfolio.repository.database.model.favorite.FavoriteModel 4 | 5 | class FavoriteClickListener(val clickListener: (item: FavoriteModel, delete: Boolean) -> Unit) { 6 | fun onClick(item: FavoriteModel, delete: Boolean) = clickListener(item, delete) 7 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/screenshot/ScreenShotClickListener.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.screenshot 2 | 3 | import me.tumur.portfolio.repository.database.model.screenshot.ScreenShotModel 4 | 5 | class ScreenShotClickListener(val clickListener: (model: ScreenShotModel) -> Unit) { 6 | fun onClick(model: ScreenShotModel) = clickListener(model) 7 | } -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Light 5 | Dark 6 | Default 7 | 8 | 9 | 10 | light 11 | dark 12 | default 13 | 14 | -------------------------------------------------------------------------------- /.idea/dictionaries/Tumur.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | appinfo 5 | bottomsheet 6 | coroutine 7 | databinding 8 | drawerlayout 9 | linkedin 10 | recyclerview 11 | sucessfull 12 | tumur 13 | viewholder 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/extensions/ViewGroupExtensions.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.extensions 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.annotation.LayoutRes 7 | 8 | fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): View { 9 | return LayoutInflater.from(context).inflate(layoutRes, this, attachToRoot) 10 | } -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_thin.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_message.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/Converters.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database 2 | 3 | import androidx.room.TypeConverter 4 | import java.util.* 5 | 6 | class Converters { 7 | @TypeConverter 8 | fun fromTimestamp(value: Long?): Date? { 9 | return value?.let { Date(it) } 10 | } 11 | 12 | @TypeConverter 13 | fun dateToTimestamp(date: Date?): Long? { 14 | return date?.time 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/repo/Repository.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.repo 2 | 3 | import me.tumur.portfolio.repository.network.Result 4 | 5 | interface Repository { 6 | 7 | /** MAIN SCREEN ------------------------------------------------------------------------------------------------- */ 8 | 9 | /** 10 | * Fetch data from network and update the database 11 | */ 12 | suspend fun fetchAll(): Result 13 | } -------------------------------------------------------------------------------- /app/src/test/java/me/tumur/portfolio/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio 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 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ... 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ... 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rounded_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_un_saved.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_play.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/constants/BsConstants.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.constants 2 | 3 | object BsConstants { 4 | 5 | /** * * * * * * * * * * * * * BOTTOM SHEET * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6 | 7 | /** Profile bottom sheet constants ----------------------------------------------------------------------------- */ 8 | const val GITHUB = "Github" 9 | const val LINKEDIN = "LinkedIn" 10 | const val TWITTER = "Twitter" 11 | const val PDF = "Resume" 12 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pdf.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/color/button_full_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_theme.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_offline.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_decorator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_dots.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_rate.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_saved.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_love_color.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_love.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /utils.gradle: -------------------------------------------------------------------------------- 1 | ext.getVersionCode = { 2 | majorVersion, minorVersion, patchVersion, buildVersion -> 3 | return majorVersion * 10000000 + minorVersion * 100000 + patchVersion * 1000 + buildVersion 4 | } 5 | 6 | ext.getVersionName = { 7 | majorVersion, minorVersion, patchVersion -> 8 | return "${majorVersion}.${minorVersion}.${patchVersion}" 9 | } 10 | 11 | ext.renameArtifact = { 12 | name, variant -> 13 | variant.outputs.all { 14 | output -> 15 | def date = new Date().format("yyyyMMdd") 16 | outputFileName = "${name}-${project.name}-${variant.versionName}-${variant.versionCode}-${date}-${variant.name}.apk" 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_favorite_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 12 | 13 | 14 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_linkedin.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_profile_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 12 | 13 | 14 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_settings_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 12 | 13 | 14 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_portfolio_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 12 | 13 | 14 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_saved.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/about/AboutItem.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.about 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import me.tumur.portfolio.repository.database.model.profile.AboutModel 5 | 6 | /** 7 | * Sealed class for composited list data 8 | * to differentiate [AboutItemViewHolder] and [AboutHeaderViewHolder] 9 | * for [RecyclerView] 10 | * */ 11 | sealed class AboutItem { 12 | data class About(val about: AboutModel): AboutItem() { 13 | override val id = about.id 14 | } 15 | 16 | data class Header(val header: String): AboutItem() { 17 | override val id = header 18 | } 19 | 20 | abstract val id: String 21 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_experience_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 12 | 13 | 14 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_youtube.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_portfolio.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_play_store.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_duration.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_top_favorite.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_save.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/button/ButtonItem.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.button 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import me.tumur.portfolio.repository.database.model.button.ButtonModel 5 | 6 | /** 7 | * Sealed class for composited list data 8 | * to differentiate [ButtonOutlineViewHolder] and [ButtonNormalViewHolder] 9 | * for [RecyclerView] 10 | * */ 11 | sealed class ButtonItem { 12 | data class ButtonOutline(val outline: ButtonModel) : ButtonItem() { 13 | override val id = outline.id 14 | } 15 | 16 | data class ButtonNormal(val normal: ButtonModel) : ButtonItem() { 17 | override val id = normal.id 18 | } 19 | 20 | abstract val id: String 21 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/androidTest/java/me/tumur/portfolio/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio 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("me.tumur.portfolio", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_twitter.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/screens/welcome/pager/WelcomePagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.screens.welcome.pager 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.Fragment 5 | import androidx.fragment.app.FragmentManager 6 | import androidx.fragment.app.FragmentStatePagerAdapter 7 | import me.tumur.portfolio.utils.constants.Constants.POSITION 8 | 9 | class WelcomePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { 10 | 11 | override fun getCount(): Int = 3 12 | 13 | override fun getItem(i: Int): Fragment { 14 | val fragment = WelcomePagerFragment() 15 | fragment.arguments = Bundle().apply { 16 | // Our object is just an integer :-P 17 | putInt(POSITION, i) 18 | } 19 | return fragment 20 | } 21 | } -------------------------------------------------------------------------------- /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 22 | -------------------------------------------------------------------------------- /app/src/main/res/color/button_outline_icon_text_border_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/favorite_list_menu.xml: -------------------------------------------------------------------------------- 1 | 3 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/menu/portfolio_list_menu.xml: -------------------------------------------------------------------------------- 1 | 3 | 10 | 11 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/screens/portfolio/detail/preview/pager/PreviewPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.screens.portfolio.detail.preview.pager 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.Fragment 5 | import androidx.fragment.app.FragmentManager 6 | import androidx.fragment.app.FragmentStatePagerAdapter 7 | import me.tumur.portfolio.utils.constants.Constants 8 | 9 | class PreviewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { 10 | 11 | override fun getCount(): Int = 6 12 | 13 | override fun getItem(i: Int): Fragment { 14 | val fragment = PreviewPagerFragment() 15 | fragment.arguments = Bundle().apply { 16 | // Our object is just an integer :-P 17 | putInt(Constants.POSITION, i) 18 | } 19 | return fragment 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/delegates/Databinding.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.delegates 2 | 3 | import android.app.Activity 4 | import androidx.annotation.LayoutRes 5 | import androidx.databinding.DataBindingUtil 6 | import androidx.databinding.ViewDataBinding 7 | import kotlin.properties.ReadOnlyProperty 8 | import kotlin.reflect.KProperty 9 | 10 | internal class ActivityBindingProperty(@LayoutRes private val resId: Int) : 11 | ReadOnlyProperty { 12 | 13 | private var binding: T? = null 14 | 15 | override operator fun getValue(thisRef: Activity, property: KProperty<*>): T { 16 | return binding ?: createActivityBinding(thisRef).also { binding = it } 17 | } 18 | 19 | private fun createActivityBinding(activity: Activity): T { 20 | return DataBindingUtil.setContentView(activity, resId) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/toolbar/CollapsibleToolbar.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.toolbar 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.constraintlayout.motion.widget.MotionLayout 6 | import com.google.android.material.appbar.AppBarLayout 7 | 8 | class CollapsibleToolbar @JvmOverloads constructor( 9 | context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 10 | ) : MotionLayout(context, attrs, defStyleAttr), AppBarLayout.OnOffsetChangedListener { 11 | 12 | override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) { 13 | progress = -verticalOffset / appBarLayout?.totalScrollRange?.toFloat()!! 14 | } 15 | 16 | override fun onAttachedToWindow() { 17 | super.onAttachedToWindow() 18 | (parent as? AppBarLayout)?.addOnOffsetChangedListener(this) 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/res/menu/bottom_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/app/AppDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.app 2 | 3 | import androidx.recyclerview.widget.DiffUtil 4 | import me.tumur.portfolio.repository.database.model.settings.AppModel 5 | 6 | /** 7 | * Callback for calculating the diff between two non-null items in a list. 8 | * 9 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 10 | * list that's been passed to `submitList`. 11 | */ 12 | 13 | class AppDiffCallBack: DiffUtil.ItemCallback() { 14 | override fun areItemsTheSame(oldItem: AppModel, newItem: AppModel): Boolean { 15 | return oldItem.title == newItem.title 16 | } 17 | 18 | override fun areContentsTheSame(oldItem: AppModel, newItem: AppModel): Boolean { 19 | return oldItem == newItem 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_map.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/about/AboutDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.about 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | 6 | /** 7 | * Callback for calculating the diff between two non-null items in a list. 8 | * 9 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 10 | * list that's been passed to `submitList`. 11 | */ 12 | 13 | class AboutDiffCallBack: DiffUtil.ItemCallback() { 14 | override fun areItemsTheSame(oldItem: AboutItem, newItem: AboutItem): Boolean { 15 | return oldItem.id == newItem.id 16 | } 17 | 18 | @SuppressLint("DiffUtilEquals") 19 | override fun areContentsTheSame(oldItem: AboutItem, newItem: AboutItem): Boolean { 20 | return oldItem == newItem 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_welcome.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/social/SocialDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.social 2 | 3 | import androidx.recyclerview.widget.DiffUtil 4 | import me.tumur.portfolio.repository.database.model.profile.SocialModel 5 | 6 | /** 7 | * Callback for calculating the diff between two non-null items in a list. 8 | * 9 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 10 | * list that's been passed to `submitList`. 11 | */ 12 | 13 | class SocialDiffCallBack: DiffUtil.ItemCallback() { 14 | override fun areItemsTheSame(oldItem: SocialModel, newItem: SocialModel): Boolean { 15 | return oldItem.name == newItem.name 16 | } 17 | 18 | override fun areContentsTheSame(oldItem: SocialModel, newItem: SocialModel): Boolean { 19 | return oldItem == newItem 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_rate.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/settings/AppDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.settings 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.settings.AppModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | @Dao 9 | abstract class AppDao { 10 | 11 | /** Update */ 12 | @Transaction 13 | open suspend fun update(list: List) { 14 | delete() 15 | insert(list) 16 | } 17 | 18 | /** Insert */ 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | abstract suspend fun insert(list: List): List 21 | 22 | /** Delete */ 23 | @Query(DbConstants.APP_DELETE) 24 | abstract suspend fun delete() 25 | 26 | /** Get list items */ 27 | @Query(DbConstants.APP_GET_LIST_ITEMS) 28 | abstract fun getListItems(): LiveData> 29 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/settings/AppModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.settings 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.PrimaryKey 7 | import com.google.gson.annotations.SerializedName 8 | import kotlinx.android.parcel.Parcelize 9 | import me.tumur.portfolio.utils.constants.DbConstants 10 | 11 | @Entity(tableName = DbConstants.APP) 12 | @Parcelize 13 | data class AppModel( 14 | @PrimaryKey(autoGenerate = false) 15 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 16 | @SerializedName(DbConstants.TITLE) @ColumnInfo(name = DbConstants.TITLE) var title: String, 17 | @SerializedName(DbConstants.TEXT) @ColumnInfo(name = DbConstants.TEXT) var text: String, 18 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 19 | ): Parcelable -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_profile.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/profile/AboutDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.profile 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.profile.AboutModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | @Dao 9 | abstract class AboutDao { 10 | 11 | /** Update */ 12 | @Transaction 13 | open suspend fun update(list: List) { 14 | delete() 15 | insert(list) 16 | } 17 | 18 | /** Insert */ 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | abstract suspend fun insert(list: List): List 21 | 22 | /** Delete */ 23 | @Query(DbConstants.ABOUT_DELETE) 24 | abstract suspend fun delete() 25 | 26 | /** Get list items */ 27 | @Query(DbConstants.ABOUT_GET_LIST_ITEMS) 28 | abstract fun getListItems(id: String): LiveData> 29 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/profile/SocialDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.profile 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.profile.SocialModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | @Dao 9 | abstract class SocialDao { 10 | 11 | /** Update */ 12 | @Transaction 13 | open suspend fun update(list: List) { 14 | delete() 15 | insert(list) 16 | } 17 | 18 | /** Insert */ 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | abstract suspend fun insert(list: List): List 21 | 22 | /** Delete */ 23 | @Query(DbConstants.SOCIAL_DELETE) 24 | abstract suspend fun delete() 25 | 26 | /** Get list items */ 27 | @Query(DbConstants.SOCIAL_GET_LIST_ITEMS) 28 | abstract fun getListItems(id: String): LiveData> 29 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/task/TaskDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.task 2 | 3 | import androidx.paging.DataSource 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.task.TaskModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | @Dao 9 | abstract class TaskDao { 10 | 11 | /** Update */ 12 | @Transaction 13 | open suspend fun update(list: List): List { 14 | delete() 15 | return insert(list) 16 | } 17 | 18 | /** Insert */ 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | abstract suspend fun insert(list: List): List 21 | 22 | /** Delete */ 23 | @Query(DbConstants.TASK_DELETE) 24 | abstract suspend fun delete() 25 | 26 | /** Get list items */ 27 | @Query(DbConstants.TASK_GET_LIST_ITEMS) 28 | abstract fun getListItems(id: String): DataSource.Factory 29 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/profile/ProfileDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.profile 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.profile.ProfileModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | @Dao 9 | abstract class ProfileDao { 10 | 11 | /** Update */ 12 | @Transaction 13 | open suspend fun update(list: List) { 14 | delete() 15 | insert(list) 16 | } 17 | 18 | /** Delete */ 19 | @Query(DbConstants.PROFILE_DELETE) 20 | abstract suspend fun delete() 21 | 22 | /** Insert */ 23 | @Insert(onConflict = OnConflictStrategy.REPLACE) 24 | abstract suspend fun insert(list: List) 25 | 26 | /** Get single item */ 27 | @Query(DbConstants.PROFILE_GET_SINGLE_ITEM) 28 | abstract fun getSingleItem(id: String): LiveData 29 | 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_github.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/about/AboutItemViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.about 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemAboutBinding 7 | 8 | /** 9 | * About item viewholder 10 | * */ 11 | class AboutItemViewHolder private constructor(val binding: ListItemAboutBinding) : RecyclerView.ViewHolder(binding.root){ 12 | fun bind(item: AboutItem.About){ 13 | binding.item = item 14 | binding.executePendingBindings() 15 | } 16 | 17 | companion object { 18 | fun from(parent: ViewGroup): AboutItemViewHolder { 19 | val layoutInflater = LayoutInflater.from(parent.context) 20 | val binding = ListItemAboutBinding.inflate(layoutInflater, parent, false) 21 | return AboutItemViewHolder(binding) 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/button/ButtonDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.button 2 | 3 | import androidx.paging.DataSource 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.button.ButtonModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | @Dao 9 | abstract class ButtonDao { 10 | 11 | /** Update */ 12 | @Transaction 13 | open suspend fun update(list: List): List { 14 | delete() 15 | return insert(list) 16 | } 17 | 18 | /** Insert */ 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | abstract suspend fun insert(list: List): List 21 | 22 | /** Delete */ 23 | @Query(DbConstants.BUTTON_DELETE) 24 | abstract suspend fun delete() 25 | 26 | /** Get list items */ 27 | @Query(DbConstants.BUTTON_GET_LIST_ITEMS) 28 | abstract fun getListItems(id: String): DataSource.Factory 29 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/location/LocationDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.location 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.LocationModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | @Dao 9 | abstract class LocationDao { 10 | 11 | /** Update */ 12 | @Transaction 13 | open suspend fun update(list: List): List { 14 | delete() 15 | return insert(list) 16 | } 17 | 18 | /** Insert */ 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | abstract suspend fun insert(list: List): List 21 | 22 | /** Delete */ 23 | @Query(DbConstants.LOCATION_DELETE) 24 | abstract suspend fun delete() 25 | 26 | 27 | /** Get single item */ 28 | @Query(DbConstants.LOCATION_GET_SINGLE_ITEM) 29 | abstract fun getSingleItem(id: String): LiveData 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/category/CategoryDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.category 2 | 3 | import androidx.paging.DataSource 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.category.CategoryModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | @Dao 9 | abstract class CategoryDao { 10 | 11 | /** Update */ 12 | @Transaction 13 | open suspend fun update(list: List): List { 14 | delete() 15 | return insert(list) 16 | } 17 | 18 | /** Insert */ 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | abstract suspend fun insert(list: List): List 21 | 22 | /** Delete */ 23 | @Query(DbConstants.CATEGORY_DELETE) 24 | abstract suspend fun delete() 25 | 26 | /** Get list items */ 27 | @Query(DbConstants.CATEGORY_GET_LIST_ITEMS) 28 | abstract fun getListItems(type: Int): DataSource.Factory 29 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/task/TaskDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience.task 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | import me.tumur.portfolio.repository.database.model.task.TaskModel 6 | 7 | /** 8 | * Callback for calculating the diff between two non-null items in a list. 9 | * 10 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 11 | * list that's been passed to `submitList`. 12 | */ 13 | 14 | class TaskDiffCallBack : DiffUtil.ItemCallback() { 15 | override fun areItemsTheSame(oldItem: TaskModel, newItem: TaskModel): Boolean { 16 | return oldItem.id == newItem.id 17 | } 18 | 19 | @SuppressLint("DiffUtilEquals") 20 | override fun areContentsTheSame(oldItem: TaskModel, newItem: TaskModel): Boolean { 21 | return oldItem == newItem 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/about/AboutHeaderViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.about 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemAboutHeaderBinding 7 | 8 | /** 9 | * About item's header viewholder 10 | * */ 11 | class AboutHeaderViewHolder private constructor(val binding: ListItemAboutHeaderBinding) : RecyclerView.ViewHolder(binding.root){ 12 | fun bind(header: AboutItem.Header){ 13 | binding.header = header 14 | binding.executePendingBindings() 15 | } 16 | 17 | companion object { 18 | fun from(parent: ViewGroup): AboutHeaderViewHolder { 19 | val layoutInflater = LayoutInflater.from(parent.context) 20 | val binding = ListItemAboutHeaderBinding.inflate(layoutInflater, parent, false) 21 | return AboutHeaderViewHolder(binding) 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_link.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/favorite/FavoriteDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.favorite 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | import me.tumur.portfolio.repository.database.model.favorite.FavoriteModel 6 | 7 | /** 8 | * Callback for calculating the diff between two non-null items in a list. 9 | * 10 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 11 | * list that's been passed to `submitList`. 12 | */ 13 | 14 | class FavoriteDiffCallBack : DiffUtil.ItemCallback() { 15 | override fun areItemsTheSame(oldItem: FavoriteModel, newItem: FavoriteModel): Boolean { 16 | return oldItem.id == newItem.id 17 | } 18 | 19 | @SuppressLint("DiffUtilEquals") 20 | override fun areContentsTheSame(oldItem: FavoriteModel, newItem: FavoriteModel): Boolean { 21 | return oldItem == newItem 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/button/ButtonDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.button 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | import me.tumur.portfolio.repository.database.model.button.ButtonModel 6 | 7 | /** 8 | * Callback for calculating the diff between two non-null items in a list. 9 | * 10 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 11 | * list that's been passed to `submitList`. 12 | */ 13 | 14 | class ButtonDiffCallBack : DiffUtil.ItemCallback() { 15 | override fun areItemsTheSame(oldItem: ButtonModel, newItem: ButtonModel): Boolean { 16 | return oldItem.id == newItem.id 17 | } 18 | 19 | @SuppressLint("DiffUtilEquals") 20 | override fun areContentsTheSame(oldItem: ButtonModel, newItem: ButtonModel): Boolean { 21 | return oldItem == newItem 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/task/TaskModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.task 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.Index 7 | import androidx.room.PrimaryKey 8 | import com.google.gson.annotations.SerializedName 9 | import kotlinx.android.parcel.Parcelize 10 | import me.tumur.portfolio.utils.constants.DbConstants 11 | 12 | @Entity(tableName = DbConstants.TASKS, indices = [Index(value = [DbConstants.ID], unique = true)]) 13 | @Parcelize 14 | data class TaskModel( 15 | @PrimaryKey(autoGenerate = false) 16 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 17 | @SerializedName(DbConstants.OWNER_ID) @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 18 | @SerializedName(DbConstants.TASK) @ColumnInfo(name = DbConstants.TASK) var task: String, 19 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 20 | ): Parcelable -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/PortfolioDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | import me.tumur.portfolio.repository.database.model.portfolio.PortfolioModel 6 | 7 | /** 8 | * Callback for calculating the diff between two non-null items in a list. 9 | * 10 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 11 | * list that's been passed to `submitList`. 12 | */ 13 | 14 | class PortfolioDiffCallBack: DiffUtil.ItemCallback() { 15 | override fun areItemsTheSame(oldItem: PortfolioModel, newItem: PortfolioModel): Boolean { 16 | return oldItem.id == newItem.id 17 | } 18 | 19 | @SuppressLint("DiffUtilEquals") 20 | override fun areContentsTheSame(oldItem: PortfolioModel, newItem: PortfolioModel): Boolean { 21 | return oldItem == newItem 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/theme/ThemeHelper.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.theme 2 | 3 | import android.os.Build 4 | import androidx.appcompat.app.AppCompatDelegate 5 | import me.tumur.portfolio.utils.constants.Constants 6 | 7 | object ThemeHelper { 8 | fun applyTheme(themePref: String) { 9 | when (themePref) { 10 | Constants.THEME_LIGHT -> { 11 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) 12 | } 13 | Constants.THEME_DARK -> { 14 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) 15 | } 16 | else -> { 17 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 18 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) 19 | } else { 20 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY) 21 | } 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/profile/AboutModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.profile 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.Index 6 | import androidx.room.PrimaryKey 7 | import com.google.gson.annotations.SerializedName 8 | import me.tumur.portfolio.utils.constants.DbConstants 9 | 10 | @Entity(tableName = DbConstants.ABOUT, indices = [Index(value = [DbConstants.ID], unique = true)]) 11 | data class AboutModel( 12 | @PrimaryKey(autoGenerate = false) 13 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 14 | @SerializedName(DbConstants.OWNER_ID) @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 15 | @SerializedName(DbConstants.HEADER) @ColumnInfo(name = DbConstants.HEADER) var header: String, 16 | @SerializedName(DbConstants.TEXT) @ColumnInfo(name = DbConstants.TEXT) var text: String, 17 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 18 | ) -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/ExperienceDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | import me.tumur.portfolio.repository.database.model.experience.ExperienceModel 6 | 7 | /** 8 | * Callback for calculating the diff between two non-null items in a list. 9 | * 10 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 11 | * list that's been passed to `submitList`. 12 | */ 13 | 14 | class ExperienceDiffCallBack : DiffUtil.ItemCallback() { 15 | override fun areItemsTheSame(oldItem: ExperienceModel, newItem: ExperienceModel): Boolean { 16 | return oldItem.id == newItem.id 17 | } 18 | 19 | @SuppressLint("DiffUtilEquals") 20 | override fun areContentsTheSame(oldItem: ExperienceModel, newItem: ExperienceModel): Boolean { 21 | return oldItem == newItem 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/resource/ResourceDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience.resource 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | import me.tumur.portfolio.repository.database.model.resource.ResourceModel 6 | 7 | /** 8 | * Callback for calculating the diff between two non-null items in a list. 9 | * 10 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 11 | * list that's been passed to `submitList`. 12 | */ 13 | 14 | class ResourceDiffCallBack : DiffUtil.ItemCallback() { 15 | override fun areItemsTheSame(oldItem: ResourceModel, newItem: ResourceModel): Boolean { 16 | return oldItem.id == newItem.id 17 | } 18 | 19 | @SuppressLint("DiffUtilEquals") 20 | override fun areContentsTheSame(oldItem: ResourceModel, newItem: ResourceModel): Boolean { 21 | return oldItem == newItem 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/task/TaskViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience.task 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemTaskBinding 7 | import me.tumur.portfolio.repository.database.model.task.TaskModel 8 | 9 | /** 10 | * Task viewholder 11 | * */ 12 | class TaskViewHolder private constructor(val binding: ListItemTaskBinding) : 13 | RecyclerView.ViewHolder(binding.root) { 14 | fun bind(item: TaskModel?) { 15 | binding.item = item 16 | binding.executePendingBindings() 17 | } 18 | 19 | companion object { 20 | fun from(parent: ViewGroup): TaskViewHolder { 21 | val layoutInflater = LayoutInflater.from(parent.context) 22 | val binding = ListItemTaskBinding.inflate(layoutInflater, parent, false) 23 | return TaskViewHolder(binding) 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/category/CategoryDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.category 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | import me.tumur.portfolio.repository.database.model.category.CategoryModel 6 | 7 | /** 8 | * Callback for calculating the diff between two non-null items in a list. 9 | * 10 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 11 | * list that's been passed to `submitList`. 12 | */ 13 | 14 | class CategoryDiffCallBack : DiffUtil.ItemCallback() { 15 | override fun areItemsTheSame(oldItem: CategoryModel, newItem: CategoryModel): Boolean { 16 | return oldItem.id == newItem.id 17 | } 18 | 19 | @SuppressLint("DiffUtilEquals") 20 | override fun areContentsTheSame(oldItem: CategoryModel, newItem: CategoryModel): Boolean { 21 | return oldItem == newItem 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/screenshot/ScreenShotDiffCallBack.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.screenshot 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.recyclerview.widget.DiffUtil 5 | import me.tumur.portfolio.repository.database.model.screenshot.ScreenShotModel 6 | 7 | /** 8 | * Callback for calculating the diff between two non-null items in a list. 9 | * 10 | * Used by ListAdapter or PagedListAdapter to calculate the minimum number of changes between and old list and a new 11 | * list that's been passed to `submitList`. 12 | */ 13 | 14 | class ScreenShotDiffCallBack : DiffUtil.ItemCallback() { 15 | override fun areItemsTheSame(oldItem: ScreenShotModel, newItem: ScreenShotModel): Boolean { 16 | return oldItem.id == newItem.id 17 | } 18 | 19 | @SuppressLint("DiffUtilEquals") 20 | override fun areContentsTheSame(oldItem: ScreenShotModel, newItem: ScreenShotModel): Boolean { 21 | return oldItem == newItem 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_empty.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fab_profile.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/app/AppViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.app 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemDialogAppInfoBinding 7 | import me.tumur.portfolio.repository.database.model.settings.AppModel 8 | 9 | /** 10 | * Constructor of ViewHolder 11 | * */ 12 | class AppViewHolder private constructor(val binding: ListItemDialogAppInfoBinding) : 13 | RecyclerView.ViewHolder(binding.root) { 14 | 15 | fun bind(appInfoItem: AppModel){ 16 | binding.item = appInfoItem 17 | binding.executePendingBindings() 18 | } 19 | 20 | companion object { 21 | fun from(parent: ViewGroup): AppViewHolder { 22 | val layoutInflater = LayoutInflater.from(parent.context) 23 | val binding = ListItemDialogAppInfoBinding.inflate(layoutInflater, parent, false) 24 | return AppViewHolder(binding) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/LocationModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.Index 7 | import androidx.room.PrimaryKey 8 | import com.google.gson.annotations.SerializedName 9 | import kotlinx.android.parcel.Parcelize 10 | import me.tumur.portfolio.utils.constants.DbConstants 11 | 12 | @Entity(tableName = DbConstants.LOCATION, indices = [Index(value = [DbConstants.ID], unique = true)]) 13 | @Parcelize 14 | data class LocationModel( 15 | @PrimaryKey(autoGenerate = false) 16 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 17 | @SerializedName(DbConstants.OWNER_ID) @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 18 | @SerializedName(DbConstants.LATITUDE) @ColumnInfo(name = DbConstants.LATITUDE) var latitude: Double? = null, 19 | @SerializedName(DbConstants.LONGITUDE) @ColumnInfo(name = DbConstants.LONGITUDE) var longitude: Double? = null 20 | ) : Parcelable -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/category/CategoryViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.category 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemCategoryBinding 7 | import me.tumur.portfolio.repository.database.model.category.CategoryModel 8 | 9 | /** 10 | * Category viewholder 11 | * */ 12 | class CategoryViewHolder private constructor(val binding: ListItemCategoryBinding) : 13 | RecyclerView.ViewHolder(binding.root) { 14 | fun bind(item: CategoryModel?) { 15 | binding.item = item 16 | binding.executePendingBindings() 17 | } 18 | 19 | companion object { 20 | fun from(parent: ViewGroup): CategoryViewHolder { 21 | val layoutInflater = LayoutInflater.from(parent.context) 22 | val binding = ListItemCategoryBinding.inflate(layoutInflater, parent, false) 23 | return CategoryViewHolder(binding) 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/res/menu/profile_menu.xml: -------------------------------------------------------------------------------- 1 | 3 | 10 | 11 | 17 | 18 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0dp 4 | 1dp 5 | 2dp 6 | 20dp 7 | 4dp 8 | 230dp 9 | 480dp 10 | 80 11 | 0 12 | 5sp 13 | 4sp 14 | 10sp 15 | 12sp 16 | 14sp 17 | 15sp 18 | 16sp 19 | 18sp 20 | 20sp 21 | 22sp 22 | 24sp 23 | 26sp 24 | 16dp 25 | 8dp 26 | 4dp 27 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/resource/ResourceDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.resource 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.paging.DataSource 5 | import androidx.room.* 6 | import me.tumur.portfolio.repository.database.model.resource.ResourceModel 7 | import me.tumur.portfolio.utils.constants.DbConstants 8 | 9 | @Dao 10 | abstract class ResourceDao { 11 | 12 | /** Update */ 13 | @Transaction 14 | open suspend fun update(list: List) { 15 | delete() 16 | insert(list) 17 | } 18 | 19 | /** Delete */ 20 | @Query(DbConstants.RESOURCE_DELETE) 21 | abstract suspend fun delete() 22 | 23 | /** Insert */ 24 | @Insert(onConflict = OnConflictStrategy.REPLACE) 25 | abstract suspend fun insert(list: List) 26 | 27 | /** Get list items */ 28 | @Query(DbConstants.RESOURCE_GET_LIST_ITEMS) 29 | abstract fun getListItems(id: String): DataSource.Factory 30 | 31 | /** Check table */ 32 | @Query(DbConstants.RESOURCE_CHECK) 33 | abstract fun check(id: String): LiveData 34 | 35 | 36 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/profile/SocialModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.profile 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.Index 7 | import androidx.room.PrimaryKey 8 | import com.google.gson.annotations.SerializedName 9 | import kotlinx.android.parcel.Parcelize 10 | import me.tumur.portfolio.utils.constants.DbConstants 11 | 12 | @Entity(tableName = DbConstants.SOCIAL, indices = [Index(value = [DbConstants.ID, DbConstants.OWNER_ID], unique = true)]) 13 | @Parcelize 14 | data class SocialModel( 15 | @PrimaryKey(autoGenerate = false) 16 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 17 | @SerializedName(DbConstants.OWNER_ID) @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 18 | @SerializedName(DbConstants.NAME) @ColumnInfo(name = DbConstants.NAME) var name: String, 19 | @SerializedName(DbConstants.URL) @ColumnInfo(name = DbConstants.URL) var url: String, 20 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 21 | ): Parcelable -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/favorite/FavoriteViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.favorite 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemFavoriteBinding 7 | import me.tumur.portfolio.repository.database.model.favorite.FavoriteModel 8 | 9 | /** 10 | * Favorite item viewholder 11 | * */ 12 | class FavoriteViewHolder private constructor(val binding: ListItemFavoriteBinding) : 13 | RecyclerView.ViewHolder(binding.root) { 14 | fun bind(item: FavoriteModel?, clickListener: FavoriteClickListener) { 15 | binding.clickListener = clickListener 16 | binding.item = item 17 | binding.executePendingBindings() 18 | } 19 | 20 | companion object { 21 | fun from(parent: ViewGroup): FavoriteViewHolder { 22 | val layoutInflater = LayoutInflater.from(parent.context) 23 | val binding = ListItemFavoriteBinding.inflate(layoutInflater, parent, false) 24 | return FavoriteViewHolder(binding) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_privacy.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/PortfolioViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemPortfolioBinding 7 | import me.tumur.portfolio.repository.database.model.portfolio.PortfolioModel 8 | 9 | /** 10 | * Portfolio item viewholder 11 | * */ 12 | class PortfolioViewHolder private constructor(val binding: ListItemPortfolioBinding) : RecyclerView.ViewHolder(binding.root){ 13 | fun bind(item: PortfolioModel?, clickListener: PortfolioClickListener){ 14 | binding.clickListener = clickListener 15 | binding.item = item 16 | binding.executePendingBindings() 17 | } 18 | 19 | companion object { 20 | fun from(parent: ViewGroup): PortfolioViewHolder { 21 | val layoutInflater = LayoutInflater.from(parent.context) 22 | val binding = ListItemPortfolioBinding.inflate(layoutInflater, parent, false) 23 | return PortfolioViewHolder(binding) 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/welcome/WelcomeModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.welcome 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.Index 6 | import androidx.room.PrimaryKey 7 | import com.google.gson.annotations.SerializedName 8 | import me.tumur.portfolio.utils.constants.DbConstants 9 | 10 | @Entity(tableName = DbConstants.WELCOME, indices = [Index(value = [DbConstants.ID], unique = true)]) 11 | data class WelcomeModel( 12 | @PrimaryKey(autoGenerate = false) 13 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 14 | @SerializedName(DbConstants.TITLE) @ColumnInfo(name = DbConstants.TITLE) var title: String, 15 | @SerializedName(DbConstants.SUB_TITLE) @ColumnInfo(name = DbConstants.SUB_TITLE) var subTitle: String, 16 | @SerializedName(DbConstants.TEXT) @ColumnInfo(name = DbConstants.TEXT) var text: String, 17 | @SerializedName(DbConstants.IMAGE_DESCRIPTION) @ColumnInfo(name = DbConstants.IMAGE_DESCRIPTION) val imageDescription: String, 18 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 19 | ) -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/button/ButtonNormalViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.button 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemButtonBinding 7 | import me.tumur.portfolio.repository.database.model.button.ButtonModel 8 | 9 | /** 10 | * Button normal viewholder 11 | * */ 12 | class ButtonNormalViewHolder private constructor(val binding: ListItemButtonBinding) : 13 | RecyclerView.ViewHolder(binding.root) { 14 | fun bind(item: ButtonModel, clickListener: ButtonClickListener) { 15 | binding.clickListener = clickListener 16 | binding.button = item 17 | binding.executePendingBindings() 18 | } 19 | 20 | companion object { 21 | fun from(parent: ViewGroup): ButtonNormalViewHolder { 22 | val layoutInflater = LayoutInflater.from(parent.context) 23 | val binding = ListItemButtonBinding.inflate(layoutInflater, parent, false) 24 | return ButtonNormalViewHolder(binding) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_privacy.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/screenshot/ScreenShotModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.screenshot 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.Index 7 | import androidx.room.PrimaryKey 8 | import com.google.gson.annotations.SerializedName 9 | import kotlinx.android.parcel.Parcelize 10 | import me.tumur.portfolio.utils.constants.DbConstants 11 | 12 | @Entity(tableName = DbConstants.SCREENSHOT, indices = [Index(value = [DbConstants.ID], unique = true)]) 13 | @Parcelize 14 | data class ScreenShotModel( 15 | @PrimaryKey(autoGenerate = false) 16 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 17 | @SerializedName(DbConstants.OWNER_ID) @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 18 | @SerializedName(DbConstants.URL) @ColumnInfo(name = DbConstants.URL) var url: String, 19 | @SerializedName(DbConstants.DESCRIPTION) @ColumnInfo(name = DbConstants.IMAGE_DESCRIPTION) var imageDescription: String, 20 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 21 | ) : Parcelable -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/ExperienceViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemExperienceBinding 7 | import me.tumur.portfolio.repository.database.model.experience.ExperienceModel 8 | 9 | /** 10 | * Experience item viewholder 11 | * */ 12 | class ExperienceViewHolder private constructor(val binding: ListItemExperienceBinding) : 13 | RecyclerView.ViewHolder(binding.root) { 14 | fun bind(item: ExperienceModel?, clickListener: ExperienceClickListener) { 15 | binding.clickListener = clickListener 16 | binding.item = item 17 | binding.executePendingBindings() 18 | } 19 | 20 | companion object { 21 | fun from(parent: ViewGroup): ExperienceViewHolder { 22 | val layoutInflater = LayoutInflater.from(parent.context) 23 | val binding = ListItemExperienceBinding.inflate(layoutInflater, parent, false) 24 | return ExperienceViewHolder(binding) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/social/SocialViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.social 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemBsSocialBinding 7 | import me.tumur.portfolio.repository.database.model.profile.SocialModel 8 | 9 | /** 10 | * Constructor of ViewHolder 11 | * */ 12 | class SocialViewHolder private constructor(val binding: ListItemBsSocialBinding) : RecyclerView.ViewHolder(binding.root){ 13 | 14 | fun bind(socialItem: SocialModel, clickListener: SocialClickListener){ 15 | binding.clickListener = clickListener 16 | binding.social = socialItem 17 | binding.executePendingBindings() 18 | } 19 | 20 | companion object { 21 | fun from(parent: ViewGroup): SocialViewHolder { 22 | val layoutInflater = LayoutInflater.from(parent.context) 23 | val binding = ListItemBsSocialBinding.inflate(layoutInflater, parent, false) 24 | return SocialViewHolder( 25 | binding 26 | ) 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_read_more.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 9 | 11 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/button/ButtonOutlineViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.button 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemButtonOutlineBinding 7 | import me.tumur.portfolio.repository.database.model.button.ButtonModel 8 | 9 | /** 10 | * Button normal viewholder 11 | * */ 12 | class ButtonOutlineViewHolder private constructor(val binding: ListItemButtonOutlineBinding) : 13 | RecyclerView.ViewHolder(binding.root) { 14 | fun bind(item: ButtonModel, clickListener: ButtonClickListener) { 15 | binding.clickListener = clickListener 16 | binding.button = item 17 | binding.executePendingBindings() 18 | } 19 | 20 | companion object { 21 | fun from(parent: ViewGroup): ButtonOutlineViewHolder { 22 | val layoutInflater = LayoutInflater.from(parent.context) 23 | val binding = ListItemButtonOutlineBinding.inflate(layoutInflater, parent, false) 24 | return ButtonOutlineViewHolder(binding) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/screenshot/ScreenShotViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.screenshot 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemScreenshotBinding 7 | import me.tumur.portfolio.repository.database.model.screenshot.ScreenShotModel 8 | 9 | /** 10 | * Screenshot viewholder 11 | * */ 12 | class ScreenShotViewHolder private constructor(val binding: ListItemScreenshotBinding) : 13 | RecyclerView.ViewHolder(binding.root) { 14 | fun bind(item: ScreenShotModel?, clickListener: ScreenShotClickListener) { 15 | binding.clickListener = clickListener 16 | binding.item = item 17 | binding.executePendingBindings() 18 | } 19 | 20 | companion object { 21 | fun from(parent: ViewGroup): ScreenShotViewHolder { 22 | val layoutInflater = LayoutInflater.from(parent.context) 23 | val binding = ListItemScreenshotBinding.inflate(layoutInflater, parent, false) 24 | return ScreenShotViewHolder(binding) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_wifi.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/screens/welcome/pager/WelcomePagerViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.screens.welcome.pager 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | import me.tumur.portfolio.repository.database.model.welcome.WelcomeModel 7 | 8 | class WelcomePagerViewModel : ViewModel() { 9 | 10 | /** VARIABLES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 11 | 12 | /** Pager' position */ 13 | private val _position = MutableLiveData() 14 | val position: LiveData = _position 15 | 16 | /** Screen's data */ 17 | private val _data = MutableLiveData() 18 | val data: LiveData = _data 19 | 20 | /** FUNCTIONS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 21 | 22 | /** 23 | * Set pager's position 24 | * */ 25 | fun setPosition(position: Int){ 26 | _position.value = position 27 | } 28 | 29 | /** 30 | * Set screen's data 31 | * */ 32 | fun setData(model: WelcomeModel){ 33 | _data.apply { value = model } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/extensions/isNetworkAvailable.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.extensions 2 | 3 | import android.Manifest 4 | import android.content.Context 5 | import android.net.ConnectivityManager 6 | import android.net.NetworkCapabilities 7 | import android.os.Build 8 | import androidx.annotation.RequiresPermission 9 | 10 | /** 11 | * Checks network access 12 | */ 13 | @RequiresPermission(value = Manifest.permission.ACCESS_NETWORK_STATE) 14 | fun Any.isNetworkAvailable(context: Context): Boolean { 15 | val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager 16 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 17 | val nw = connectivityManager.activeNetwork ?: return false 18 | val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false 19 | return when { 20 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true 21 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true 22 | else -> false 23 | } 24 | } else { 25 | val nwInfo = connectivityManager.activeNetwork ?: return false 26 | return nwInfo.isNetworkAvailable(context) 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/button/ButtonModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.button 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.Index 7 | import androidx.room.PrimaryKey 8 | import com.google.gson.annotations.SerializedName 9 | import kotlinx.android.parcel.Parcelize 10 | import me.tumur.portfolio.utils.constants.DbConstants 11 | 12 | @Entity(tableName = DbConstants.BUTTON, indices = [Index(value = [DbConstants.ID], unique = true)]) 13 | @Parcelize 14 | data class ButtonModel( 15 | @PrimaryKey(autoGenerate = false) 16 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 17 | @SerializedName(DbConstants.OWNER_ID) @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 18 | @SerializedName(DbConstants.TITLE) @ColumnInfo(name = DbConstants.TITLE) var title: String, 19 | @SerializedName(DbConstants.URL) @ColumnInfo(name = DbConstants.URL) var url: String, 20 | @SerializedName(DbConstants.TYPE) @ColumnInfo(name = DbConstants.TYPE) var type: String, 21 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 22 | ): Parcelable -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_experience.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | 9 | 11 | 13 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/experience/ExperienceDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.experience 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.paging.DataSource 5 | import androidx.room.* 6 | import me.tumur.portfolio.repository.database.model.experience.ExperienceModel 7 | import me.tumur.portfolio.utils.constants.DbConstants 8 | 9 | @Dao 10 | abstract class ExperienceDao { 11 | 12 | /** Update */ 13 | @Transaction 14 | open suspend fun update(list: List): List { 15 | delete() 16 | return insert(list) 17 | } 18 | 19 | /** Insert */ 20 | @Insert(onConflict = OnConflictStrategy.REPLACE) 21 | abstract suspend fun insert(list: List): List 22 | 23 | /** Delete */ 24 | @Query(DbConstants.EXPERIENCE_DELETE) 25 | abstract suspend fun delete() 26 | 27 | /** Get list items */ 28 | @Query(DbConstants.EXPERIENCE_GET_LIST_ITEMS) 29 | abstract fun getListItems(id: String): DataSource.Factory 30 | 31 | 32 | /** Get single item */ 33 | @Query(DbConstants.EXPERIENCE_GET_SINGLE_ITEM) 34 | abstract fun getSingleItem(id: String): LiveData 35 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/screenshot/ScreenShotDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.screenshot 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.paging.DataSource 5 | import androidx.room.* 6 | import me.tumur.portfolio.repository.database.model.screenshot.ScreenShotModel 7 | import me.tumur.portfolio.utils.constants.DbConstants 8 | 9 | @Dao 10 | abstract class ScreenShotDao { 11 | 12 | /** Update */ 13 | @Transaction 14 | open suspend fun update(list: List): List { 15 | delete() 16 | return insert(list) 17 | } 18 | 19 | /** Insert */ 20 | @Insert(onConflict = OnConflictStrategy.REPLACE) 21 | abstract suspend fun insert(list: List): List 22 | 23 | /** Delete */ 24 | @Query(DbConstants.SCREENSHOT_DELETE) 25 | abstract suspend fun delete() 26 | 27 | /** Get paged list items */ 28 | @Query(DbConstants.SCREENSHOT_GET_LIST_ITEMS) 29 | abstract fun getPagedListItems(id: String): DataSource.Factory 30 | 31 | /** Get list items */ 32 | @Query(DbConstants.SCREENSHOT_GET_LIST_ITEMS) 33 | abstract fun getListItems(id: String): LiveData> 34 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/welcome/WelcomeDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.welcome 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.* 5 | import me.tumur.portfolio.repository.database.model.welcome.WelcomeModel 6 | import me.tumur.portfolio.utils.constants.DbConstants 7 | 8 | 9 | @Dao 10 | abstract class WelcomeDao { 11 | 12 | /** Update */ 13 | @Transaction 14 | open suspend fun update(list: List): List { 15 | delete() 16 | return insert(list) 17 | } 18 | 19 | /** Check */ 20 | @Query(DbConstants.WELCOME_CHECK) 21 | abstract suspend fun check(): Int 22 | 23 | /** Insert */ 24 | @Insert(onConflict = OnConflictStrategy.REPLACE) 25 | abstract suspend fun insert(data: List): List 26 | 27 | /** Delete */ 28 | @Query(DbConstants.WELCOME_DELETE) 29 | abstract suspend fun delete() 30 | 31 | /** Get list items */ 32 | @Query(DbConstants.WELCOME_GET_LIST_ITEMS) 33 | abstract fun getListItems(): LiveData> 34 | 35 | /** Get single item */ 36 | @Query(DbConstants.WELCOME_GET_SINGLE_ITEM) 37 | abstract fun getSingleItem(id: String): LiveData 38 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 8 | 12 | 16 | 20 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/menu/side_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | 16 | 20 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/category/CategoryModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.category 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.Index 7 | import androidx.room.PrimaryKey 8 | import com.google.gson.annotations.SerializedName 9 | import kotlinx.android.parcel.Parcelize 10 | import me.tumur.portfolio.utils.constants.DbConstants 11 | 12 | @Entity(tableName = DbConstants.CATEGORY, indices = [Index(value = [DbConstants.ID], unique = true)]) 13 | @Parcelize 14 | data class CategoryModel( 15 | @PrimaryKey(autoGenerate = false) 16 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 17 | @SerializedName(DbConstants.TITLE) @ColumnInfo(name = DbConstants.TITLE) var title: String, 18 | @SerializedName(DbConstants.TYPE) @ColumnInfo(name = DbConstants.TYPE) var type: Int, 19 | @SerializedName(DbConstants.ICON) @ColumnInfo(name = DbConstants.ICON) var icon: String, 20 | @SerializedName(DbConstants.ICON_DESCRIPTION) @ColumnInfo(name = DbConstants.ICON_DESCRIPTION) var iconDescription: String, 21 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 22 | ) : Parcelable -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/resource/ResourceViewHolder.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience.resource 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.databinding.ListItemResourceBinding 7 | import me.tumur.portfolio.repository.database.model.resource.ResourceModel 8 | import me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.button.ButtonClickListener 9 | 10 | /** 11 | * Resource item viewholder 12 | * */ 13 | class ResourceViewHolder private constructor(val binding: ListItemResourceBinding) : 14 | RecyclerView.ViewHolder(binding.root) { 15 | fun bind(item: ResourceModel?, clickListener: ButtonClickListener) { 16 | binding.clickListener = clickListener 17 | binding.item = item 18 | binding.executePendingBindings() 19 | } 20 | 21 | companion object { 22 | fun from(parent: ViewGroup): ResourceViewHolder { 23 | val layoutInflater = LayoutInflater.from(parent.context) 24 | val binding = ListItemResourceBinding.inflate(layoutInflater, parent, false) 25 | return ResourceViewHolder(binding) 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_avatar_placeholder.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 7 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_profile_placeholder.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 7 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/screens/settings/dialog/AppDialogViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.screens.settings.dialog 2 | 3 | import androidx.lifecycle.* 4 | import kotlinx.coroutines.Dispatchers 5 | import me.tumur.portfolio.repository.database.dao.settings.AppDao 6 | import org.koin.core.KoinComponent 7 | import org.koin.core.inject 8 | 9 | class AppDialogViewModel: ViewModel(), KoinComponent{ 10 | 11 | /** VARIABLES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | /** RepositoryImp */ 14 | private val appDao: AppDao by inject() 15 | 16 | /** Profile data */ 17 | val appInfo = liveData(context = viewModelScope.coroutineContext + Dispatchers.IO){ 18 | emitSource(appDao.getListItems()) 19 | } 20 | 21 | /** Close button on click */ 22 | private val _closeButtonOnClick = MutableLiveData().apply { value = false } 23 | val closeButtonOnClick: LiveData = _closeButtonOnClick 24 | 25 | /** FUNCTIONS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 26 | 27 | /** 28 | * Set close button onClick event 29 | * */ 30 | fun setCloseButtonOnClick(status: Boolean){ 31 | _closeButtonOnClick.apply { value = status } 32 | } 33 | } -------------------------------------------------------------------------------- /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=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec: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 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | kapt.incremental.apt=true 23 | GOOGLE_MAPS_API_KEY=AIzaSyDJrKxFSF3DIvtWmlTTQQKf1OvYsd9YDtY 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/screen_profile_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_refresh.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_experience.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/preference_category_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 26 | 27 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Android 17 | 18 | 19 | CorrectnessLintAndroid 20 | 21 | 22 | General 23 | 24 | 25 | Kotlin 26 | 27 | 28 | LintAndroid 29 | 30 | 31 | PerformanceLintAndroid 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 8 | 11 | 15 | 19 | 23 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/portfolio/PortfolioDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.portfolio 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.paging.DataSource 5 | import androidx.room.* 6 | import me.tumur.portfolio.repository.database.model.portfolio.PortfolioModel 7 | import me.tumur.portfolio.utils.constants.DbConstants 8 | 9 | @Dao 10 | abstract class PortfolioDao { 11 | 12 | /** Update */ 13 | @Transaction 14 | open suspend fun update(list: List): List { 15 | delete() 16 | return insert(list) 17 | } 18 | 19 | /** Insert */ 20 | @Insert(onConflict = OnConflictStrategy.REPLACE) 21 | abstract suspend fun insert(list: List): List 22 | 23 | /** Delete */ 24 | @Query(DbConstants.PORTFOLIO_DELETE) 25 | abstract suspend fun delete() 26 | 27 | /** Get list items */ 28 | @Query(DbConstants.PORTFOLIO_GET_LIST_ITEMS) 29 | abstract fun getListItems(id: String): DataSource.Factory 30 | 31 | 32 | /** Get single item */ 33 | @Query(DbConstants.PORTFOLIO_GET_SINGLE_ITEM) 34 | abstract fun getSingleItem(id: String): LiveData 35 | 36 | // /** Search by query */ 37 | // @Query(DbConstants.GET_PORTFOLIO_BY_QUERY) 38 | // abstract fun getByQuery(query: String): LiveData> 39 | 40 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/preference_category_footer.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/profile/ProfileModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.profile 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.Index 6 | import androidx.room.PrimaryKey 7 | import com.google.gson.annotations.SerializedName 8 | import me.tumur.portfolio.utils.constants.DbConstants 9 | 10 | @Entity( 11 | tableName = DbConstants.PROFILE, 12 | indices = [Index(value = [DbConstants.ID, DbConstants.NAME], unique = true)] 13 | ) 14 | data class ProfileModel( 15 | @PrimaryKey(autoGenerate = false) 16 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 17 | @SerializedName(DbConstants.GREETING) @ColumnInfo(name = DbConstants.GREETING) var greeting: String, 18 | @SerializedName(DbConstants.NAME) @ColumnInfo(name = DbConstants.NAME) var name: String, 19 | @SerializedName(DbConstants.TITLE) @ColumnInfo(name = DbConstants.TITLE) var title: String, 20 | @SerializedName(DbConstants.IMAGE) @ColumnInfo(name = DbConstants.IMAGE) var image: String, 21 | @SerializedName(DbConstants.IMAGE_DESCRIPTION) @ColumnInfo(name = DbConstants.IMAGE_DESCRIPTION) var imageDescription: String, 22 | @SerializedName(DbConstants.EMAIL) @ColumnInfo(name = DbConstants.EMAIL) var email: String, 23 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 24 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_globe.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/task/TaskAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience.task 2 | 3 | import android.view.ViewGroup 4 | import androidx.paging.PagedListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.task.TaskModel 7 | 8 | /** 9 | * An adapter that provides a list of [TaskModel] to a [RecyclerView] 10 | * */ 11 | 12 | class TaskAdapter : PagedListAdapter(TaskDiffCallBack()) { 13 | 14 | /** 15 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [TaskViewHolder] 16 | * 17 | * A [TaskViewHolder] holds the view for the [RecyclerView] as well as providing information 18 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 19 | * */ 20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder { 21 | return TaskViewHolder.from(parent) 22 | } 23 | 24 | /** 25 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 26 | * 27 | * The [TaskViewHolder] passed may be recycled so make sure that this sets any properties 28 | * that may be have been set previously 29 | * */ 30 | override fun onBindViewHolder(holder: TaskViewHolder, position: Int) { 31 | holder.bind(getItem(position)) 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_email.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/app/AppAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.app 2 | 3 | import android.view.ViewGroup 4 | import androidx.recyclerview.widget.ListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.settings.AppModel 7 | 8 | /** 9 | * An adapter that provides a list of [AppModel] to a [RecyclerView] 10 | * */ 11 | 12 | class AppAdapter: ListAdapter(AppDiffCallBack()) { 13 | 14 | /** 15 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [AppViewHolder] 16 | * 17 | * A [AppViewHolder] holds the view for the [RecyclerView] as well as providing information 18 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 19 | * */ 20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder { 21 | return AppViewHolder.from(parent) 22 | } 23 | 24 | /** 25 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 26 | * 27 | * The [AppViewHolder] passed may be recycled so make sure that this sets any properties 28 | * that may be have been set previously 29 | * */ 30 | override fun onBindViewHolder(holder: AppViewHolder, position: Int) { 31 | val appInfoItem = getItem(position) 32 | holder.bind(appInfoItem) 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_logo.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 13 | 17 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_settings.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/category/CategoryAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.category 2 | 3 | import android.view.ViewGroup 4 | import androidx.paging.PagedListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.category.CategoryModel 7 | 8 | /** 9 | * An adapter that provides a list of [CategoryModel] to a [RecyclerView] 10 | * */ 11 | 12 | class CategoryAdapter : PagedListAdapter(CategoryDiffCallBack()) { 13 | 14 | /** 15 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [CategoryViewHolder] 16 | * 17 | * A [CategoryViewHolder] holds the view for the [RecyclerView] as well as providing information 18 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 19 | * */ 20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryViewHolder { 21 | return CategoryViewHolder.from(parent) 22 | } 23 | 24 | /** 25 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 26 | * 27 | * The [CategoryViewHolder] passed may be recycled so make sure that this sets any properties 28 | * that may be have been set previously 29 | * */ 30 | override fun onBindViewHolder(holder: CategoryViewHolder, position: Int) { 31 | holder.bind(getItem(position)) 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_category_code.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 24 | 30 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_no_connection.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 25 | -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "852832723346", 4 | "firebase_url": "https://portfolio-app-147b5.firebaseio.com", 5 | "project_id": "portfolio-app-147b5", 6 | "storage_bucket": "portfolio-app-147b5.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:852832723346:android:c8b206b00866c4fa", 12 | "android_client_info": { 13 | "package_name": "me.tumur.portfolio" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "852832723346-ddic85s6rk4gb9b9e7t6c85ig7733n0s.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "me.tumur.portfolio", 22 | "certificate_hash": "d7ad4634a38255ed8eda9e62be06a518d53f28ea" 23 | } 24 | }, 25 | { 26 | "client_id": "852832723346-ldtgti7i46pk2fe8tbc9b2k3ak7bun1s.apps.googleusercontent.com", 27 | "client_type": 3 28 | } 29 | ], 30 | "api_key": [ 31 | { 32 | "current_key": "AIzaSyB2X5f4wo6QC9Pgrz3mcms5-Z0n0gWQx-M" 33 | } 34 | ], 35 | "services": { 36 | "appinvite_service": { 37 | "other_platform_oauth_client": [ 38 | { 39 | "client_id": "852832723346-ldtgti7i46pk2fe8tbc9b2k3ak7bun1s.apps.googleusercontent.com", 40 | "client_type": 3 41 | } 42 | ] 43 | } 44 | } 45 | } 46 | ], 47 | "configuration_version": "1" 48 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/social/SocialAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.social 2 | 3 | import android.view.ViewGroup 4 | import androidx.recyclerview.widget.ListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.profile.SocialModel 7 | 8 | /** 9 | * An adapter that provides a list of [SocialModel] to a [RecyclerView] 10 | * */ 11 | 12 | class SocialAdapter(private val clickListener: SocialClickListener): ListAdapter(SocialDiffCallBack()) { 13 | 14 | /** 15 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [SocialViewHolder] 16 | * 17 | * A [SocialViewHolder] holds the view for the [RecyclerView] as well as providing information 18 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 19 | * */ 20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SocialViewHolder { 21 | return SocialViewHolder.from(parent) 22 | } 23 | 24 | /** 25 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 26 | * 27 | * The [SocialViewHolder] passed may be recycled so make sure that this sets any properties 28 | * that may be have been set previously 29 | * */ 30 | override fun onBindViewHolder(holder: SocialViewHolder, position: Int) { 31 | val socialItem = getItem(position) 32 | holder.bind(socialItem, clickListener) 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/favorite/FavoriteAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.favorite 2 | 3 | import android.view.ViewGroup 4 | import androidx.paging.PagedListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.favorite.FavoriteModel 7 | 8 | /** 9 | * An adapter that provides a list of [FavoriteModel] to a [RecyclerView] 10 | * */ 11 | 12 | class FavoriteAdapter(private val clickListener: FavoriteClickListener) : 13 | PagedListAdapter(FavoriteDiffCallBack()) { 14 | 15 | /** 16 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [FavoriteViewHolder] 17 | * 18 | * A [FavoriteViewHolder] holds the view for the [RecyclerView] as well as providing information 19 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 20 | * */ 21 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder { 22 | return FavoriteViewHolder.from(parent) 23 | } 24 | 25 | /** 26 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 27 | * 28 | * The [FavoriteViewHolder] passed may be recycled so make sure that this sets any properties 29 | * that may be have been set previously 30 | * */ 31 | override fun onBindViewHolder(holder: FavoriteViewHolder, position: Int) { 32 | val favoriteItem = getItem(position) 33 | holder.bind(favoriteItem, clickListener) 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/resource/ResourceModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.resource 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.Index 7 | import androidx.room.PrimaryKey 8 | import com.google.gson.annotations.SerializedName 9 | import kotlinx.android.parcel.Parcelize 10 | import me.tumur.portfolio.utils.constants.DbConstants 11 | import java.util.* 12 | 13 | @Entity(tableName = DbConstants.RESOURCE, indices = [Index(value = [DbConstants.ID], unique = true)]) 14 | @Parcelize 15 | data class ResourceModel( 16 | @PrimaryKey(autoGenerate = false) 17 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 18 | @SerializedName(DbConstants.OWNER_ID) @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 19 | @SerializedName(DbConstants.TITLE) @ColumnInfo(name = DbConstants.TITLE) var title: String, 20 | @SerializedName(DbConstants.IMAGE) @ColumnInfo(name = DbConstants.IMAGE) var image: String, 21 | @SerializedName(DbConstants.IMAGE_DESCRIPTION) @ColumnInfo(name = DbConstants.IMAGE_DESCRIPTION) var imageDescription: String, 22 | @SerializedName(DbConstants.DATE_FROM) @ColumnInfo(name = DbConstants.DATE_FROM) var dateFrom: Date, 23 | @SerializedName(DbConstants.DATE_TO) @ColumnInfo(name = DbConstants.DATE_TO) var dateTo: Date, 24 | @SerializedName(DbConstants.URL) @ColumnInfo(name = DbConstants.URL) var url: String?, 25 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 26 | ) : Parcelable -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/PortfolioAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio 2 | 3 | import android.view.ViewGroup 4 | import androidx.paging.PagedListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.portfolio.PortfolioModel 7 | 8 | /** 9 | * An adapter that provides a list of [PortfolioModel] to a [RecyclerView] 10 | * */ 11 | 12 | class PortfolioAdapter(private val clickListener: PortfolioClickListener) : PagedListAdapter(PortfolioDiffCallBack()) { 13 | 14 | /** 15 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [PortfolioViewHolder] 16 | * 17 | * A [PortfolioViewHolder] holds the view for the [RecyclerView] as well as providing information 18 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 19 | * */ 20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PortfolioViewHolder { 21 | return PortfolioViewHolder.from(parent) 22 | } 23 | 24 | /** 25 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 26 | * 27 | * The [PortfolioViewHolder] passed may be recycled so make sure that this sets any properties 28 | * that may be have been set previously 29 | * */ 30 | override fun onBindViewHolder(holder: PortfolioViewHolder, position: Int) { 31 | val portfolioItem = getItem(position) 32 | holder.bind(portfolioItem, clickListener) 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/portfolio/screenshot/ScreenShotAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.screenshot 2 | 3 | import android.view.ViewGroup 4 | import androidx.paging.PagedListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.screenshot.ScreenShotModel 7 | 8 | /** 9 | * An adapter that provides a list of [ScreenShotModel] to a [RecyclerView] 10 | * */ 11 | 12 | class ScreenShotAdapter(private val clickListener: ScreenShotClickListener) : 13 | PagedListAdapter(ScreenShotDiffCallBack()) { 14 | 15 | /** 16 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [ScreenShotViewHolder] 17 | * 18 | * A [ScreenShotViewHolder] holds the view for the [RecyclerView] as well as providing information 19 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 20 | * */ 21 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ScreenShotViewHolder { 22 | return ScreenShotViewHolder.from(parent) 23 | } 24 | 25 | /** 26 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 27 | * 28 | * The [ScreenShotViewHolder] passed may be recycled so make sure that this sets any properties 29 | * that may be have been set previously 30 | * */ 31 | override fun onBindViewHolder(holder: ScreenShotViewHolder, position: Int) { 32 | holder.bind(getItem(position), clickListener) 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_hand_waving.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/ExperienceAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience 2 | 3 | import android.view.ViewGroup 4 | import androidx.paging.PagedListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.experience.ExperienceModel 7 | 8 | /** 9 | * An adapter that provides a list of [ExperienceModel] to a [RecyclerView] 10 | * */ 11 | 12 | class ExperienceAdapter(private val clickListener: ExperienceClickListener) : 13 | PagedListAdapter( 14 | ExperienceDiffCallBack() 15 | ) { 16 | 17 | /** 18 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [ExperienceViewHolder] 19 | * 20 | * A [ExperienceViewHolder] holds the view for the [RecyclerView] as well as providing information 21 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 22 | * */ 23 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExperienceViewHolder { 24 | return ExperienceViewHolder.from(parent) 25 | } 26 | 27 | /** 28 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 29 | * 30 | * The [ExperienceViewHolder] passed may be recycled so make sure that this sets any properties 31 | * that may be have been set previously 32 | * */ 33 | override fun onBindViewHolder(holder: ExperienceViewHolder, position: Int) { 34 | val experienceItem = getItem(position) 35 | holder.bind(experienceItem, clickListener) 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/screens/portfolio/detail/preview/pager/PreviewPagerViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.screens.portfolio.detail.preview.pager 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | import me.tumur.portfolio.repository.database.model.screenshot.ScreenShotModel 7 | import me.tumur.portfolio.utils.state.PreviewState 8 | import me.tumur.portfolio.utils.state.ProgressBar 9 | import org.koin.core.KoinComponent 10 | 11 | class PreviewPagerViewModel : ViewModel(), KoinComponent { 12 | 13 | /** VARIABLES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | /** Position */ 16 | private val _position = MutableLiveData() 17 | val position: LiveData = _position 18 | 19 | /** Screenshot */ 20 | private val _data = MutableLiveData() 21 | val data: LiveData = _data 22 | 23 | /** State */ 24 | private val _state = MutableLiveData().apply { value = ProgressBar } 25 | val state: LiveData = _state 26 | 27 | /** FUNCTIONS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 28 | 29 | /** 30 | * Set position 31 | * */ 32 | fun setPosition(position: Int) { 33 | _position.value = position 34 | } 35 | 36 | /** 37 | * Set data 38 | * */ 39 | fun setData(screenshot: ScreenShotModel) { 40 | _data.value = screenshot 41 | } 42 | 43 | /** 44 | * Set state 45 | * */ 46 | fun setState(state: PreviewState) { 47 | _state.value = state 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/screens/experience/ExperienceViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.screens.experience 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | import androidx.paging.PagedList 7 | import androidx.paging.toLiveData 8 | import me.tumur.portfolio.repository.database.dao.experience.ExperienceDao 9 | import me.tumur.portfolio.repository.database.model.experience.ExperienceModel 10 | import me.tumur.portfolio.utils.constants.DbConstants 11 | import org.koin.core.KoinComponent 12 | import org.koin.core.inject 13 | 14 | class ExperienceViewModel : ViewModel(), KoinComponent { 15 | 16 | /** VARIABLES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 17 | 18 | /** Repository */ 19 | private val experienceDao: ExperienceDao by inject() 20 | 21 | /** Selected item id */ 22 | private val _selectedItem = MutableLiveData() 23 | val selectedItem: LiveData = _selectedItem 24 | 25 | /** Portfolio pager data */ 26 | private val config = PagedList.Config.Builder() 27 | .setPageSize(10) 28 | .setEnablePlaceholders(true) 29 | .setInitialLoadSizeHint(5) 30 | .build() 31 | 32 | val data: LiveData> = 33 | experienceDao.getListItems(DbConstants.PERSON_ID).toLiveData(config) 34 | 35 | /** FUNCTIONS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 36 | 37 | /** 38 | * Set selected item 39 | * */ 40 | fun setSelectedItem(item: ExperienceModel?) { 41 | _selectedItem.value = item 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 34 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/adapters/listItemAdapters/experience/resource/ResourceAdapter.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.adapters.listItemAdapters.experience.resource 2 | 3 | import android.view.ViewGroup 4 | import androidx.paging.PagedListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | import me.tumur.portfolio.repository.database.model.resource.ResourceModel 7 | import me.tumur.portfolio.utils.adapters.listItemAdapters.portfolio.button.ButtonClickListener 8 | 9 | /** 10 | * An adapter that provides a list of [ResourceModel] to a [RecyclerView] 11 | * */ 12 | 13 | class ResourceAdapter(private val clickListener: ButtonClickListener) : 14 | PagedListAdapter( 15 | ResourceDiffCallBack() 16 | ) { 17 | 18 | /** 19 | * Part of the RecyclerView adapter, called when RecyclerView needs a new [ResourceViewHolder] 20 | * 21 | * A [ResourceViewHolder] holds the view for the [RecyclerView] as well as providing information 22 | * to the RecyclerView such as where on the screen it was last drawn during scrolling. 23 | * */ 24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ResourceViewHolder { 25 | return ResourceViewHolder.from(parent) 26 | } 27 | 28 | /** 29 | * Part of the RecyclerView adapter, called when the RecyclerView needs to show an item. 30 | * 31 | * The [ResourceViewHolder] passed may be recycled so make sure that this sets any properties 32 | * that may be have been set previously 33 | * */ 34 | override fun onBindViewHolder(holder: ResourceViewHolder, position: Int) { 35 | val resourceItem = getItem(position) 36 | holder.bind(resourceItem, clickListener) 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_portfolio.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/dao/favorite/FavoriteDao.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.dao.favorite 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.paging.DataSource 5 | import androidx.room.* 6 | import me.tumur.portfolio.repository.database.model.favorite.FavoriteModel 7 | import me.tumur.portfolio.utils.constants.DbConstants 8 | 9 | @Dao 10 | abstract class FavoriteDao { 11 | 12 | /** Update single item */ 13 | @Transaction 14 | open suspend fun update(item: FavoriteModel): Long { 15 | deleteSingleItem(item.id) 16 | return insert(item) 17 | } 18 | 19 | /** Insert */ 20 | @Insert(onConflict = OnConflictStrategy.REPLACE) 21 | abstract suspend fun insert(item: FavoriteModel): Long 22 | 23 | /** Delete */ 24 | @Query(DbConstants.FAVORITE_DELETE) 25 | abstract suspend fun delete() 26 | 27 | /** Delete single item */ 28 | @Query(DbConstants.FAVORITE_DELETE_SINGLE_ITEM) 29 | abstract suspend fun deleteSingleItem(id: String): Int 30 | 31 | /** Get single item */ 32 | @Query(DbConstants.FAVORITE_GET_SINGLE_ITEM) 33 | abstract fun getSingleItem(id: String): LiveData 34 | 35 | /** Get paged list items */ 36 | @Query(DbConstants.FAVORITE_GET_LIST_ITEMS) 37 | abstract fun getListItems(): DataSource.Factory 38 | 39 | /** Exist single item */ 40 | @Query(DbConstants.FAVORITE_EXIST_SINGLE_ITEM) 41 | abstract fun existSingleItem(id: String): LiveData 42 | 43 | /** Get max order */ 44 | @Query(DbConstants.FAVORITE_GET_MAX_ORDER) 45 | abstract suspend fun getMaxOrder(): FavoriteModel 46 | 47 | /** Check table */ 48 | @Query(DbConstants.FAVORITE_CHECK) 49 | abstract fun check(): LiveData 50 | } -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/favorite/FavoriteModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.favorite 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.Index 7 | import androidx.room.PrimaryKey 8 | import kotlinx.android.parcel.Parcelize 9 | import me.tumur.portfolio.utils.constants.DbConstants 10 | import java.util.* 11 | 12 | @Entity(tableName = DbConstants.FAVORITE, indices = [Index(value = [DbConstants.ID], unique = true)]) 13 | @Parcelize 14 | data class FavoriteModel( 15 | @PrimaryKey(autoGenerate = false) 16 | @ColumnInfo(name = DbConstants.ID) var id: String, 17 | @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 18 | @ColumnInfo(name = DbConstants.TITLE) var title: String, 19 | @ColumnInfo(name = DbConstants.SUB_TITLE) var subTitle: String, 20 | @ColumnInfo(name = DbConstants.LOGO) var logo: String, 21 | @ColumnInfo(name = DbConstants.LOGO_DESCRIPTION) var logoDescription: String, 22 | @ColumnInfo(name = DbConstants.COVER_IMAGE) var coverImage: String, 23 | @ColumnInfo(name = DbConstants.IMAGE_DESCRIPTION) var imageDescription: String, 24 | @ColumnInfo(name = DbConstants.TEXT) var text: String, 25 | @ColumnInfo(name = DbConstants.INFO) var info: String, 26 | @ColumnInfo(name = DbConstants.DATE_FROM) var dateFrom: Date, 27 | @ColumnInfo(name = DbConstants.DATE_TO) var dateTo: Date, 28 | @ColumnInfo(name = DbConstants.HEADER) var header: String, 29 | @ColumnInfo(name = DbConstants.TYPE) var categoryType: Int, 30 | @ColumnInfo(name = DbConstants.VIDEO_URL) var videoUrl: String?, 31 | @ColumnInfo(name = DbConstants.ORDERS) var order: Int, 32 | @ColumnInfo(name = DbConstants.DATE) var date: Date 33 | ) : Parcelable -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_category_structure.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 24 | 30 | 36 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_app_info_update.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 34 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_screenshot.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 9 | 10 | 16 | 17 | 18 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/utils/fabButton/ScrollAwareFabButton.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.utils.fabButton 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | import androidx.coordinatorlayout.widget.CoordinatorLayout 7 | import androidx.core.view.ViewCompat 8 | import com.google.android.material.floatingactionbutton.FloatingActionButton 9 | 10 | 11 | class ScrollAwareFABBehavior(context: Context, attrs: AttributeSet): FloatingActionButton.Behavior(context, attrs) { 12 | 13 | override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, 14 | child: FloatingActionButton, directTargetChild: View, target: View, 15 | axes: Int, type: Int): Boolean { 16 | return axes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, 17 | child, directTargetChild, target, axes, type) 18 | } 19 | 20 | override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, 21 | child: FloatingActionButton, target: View, dxConsumed: Int, dyConsumed: Int, 22 | dxUnconsumed: Int, dyUnconsumed: Int, type: Int) { 23 | super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, 24 | dyUnconsumed, type) 25 | 26 | if (dyConsumed > 0 && child.visibility == View.VISIBLE) { 27 | child.hide(object : FloatingActionButton.OnVisibilityChangedListener() { 28 | override fun onHidden(fab: FloatingActionButton) { 29 | super.onHidden(fab) 30 | fab.visibility = View.INVISIBLE 31 | } 32 | }) 33 | } else if (dyConsumed < 0 && child.visibility != View.VISIBLE) { 34 | child.show() 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_category_web.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_about_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/me/tumur/portfolio/repository/database/model/experience/ExperienceModel.kt: -------------------------------------------------------------------------------- 1 | package me.tumur.portfolio.repository.database.model.experience 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.Index 6 | import androidx.room.PrimaryKey 7 | import com.google.gson.annotations.SerializedName 8 | import me.tumur.portfolio.utils.constants.DbConstants 9 | import java.util.* 10 | 11 | @Entity(tableName = DbConstants.EXPERIENCE, indices = [Index(value = [DbConstants.ID], unique = true)]) 12 | data class ExperienceModel( 13 | @PrimaryKey(autoGenerate = false) 14 | @SerializedName(DbConstants.ID) @ColumnInfo(name = DbConstants.ID) var id: String, 15 | @SerializedName(DbConstants.OWNER_ID) @ColumnInfo(name = DbConstants.OWNER_ID) var ownerId: String, 16 | @SerializedName(DbConstants.TITLE) @ColumnInfo(name = DbConstants.TITLE) var title: String, 17 | @SerializedName(DbConstants.COMPANY) @ColumnInfo(name = DbConstants.COMPANY) var company: String, 18 | @SerializedName(DbConstants.INFO) @ColumnInfo(name = DbConstants.INFO) var info: String, 19 | @SerializedName(DbConstants.DATE_FROM) @ColumnInfo(name = DbConstants.DATE_FROM) var dateFrom: Date, 20 | @SerializedName(DbConstants.DATE_TO) @ColumnInfo(name = DbConstants.DATE_TO) var dateTo: Date, 21 | @SerializedName(DbConstants.LOCATION) @ColumnInfo(name = DbConstants.LOCATION) var location: String, 22 | @SerializedName(DbConstants.LOGO) @ColumnInfo(name = DbConstants.LOGO) var logo: String, 23 | @SerializedName(DbConstants.LOGO_DESCRIPTION) @ColumnInfo(name = DbConstants.LOGO_DESCRIPTION) var logoDescription: String, 24 | @SerializedName(DbConstants.COVER_IMAGE) @ColumnInfo(name = DbConstants.COVER_IMAGE) var coverImage: String, 25 | @SerializedName(DbConstants.IMAGE_DESCRIPTION) @ColumnInfo(name = DbConstants.IMAGE_DESCRIPTION) var imageDescription: String, 26 | @SerializedName(DbConstants.ORDER) @ColumnInfo(name = DbConstants.ORDERS) var order: Int 27 | ) -------------------------------------------------------------------------------- /app/src/main/res/layout/preference_item_icon_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 24 | 25 | 26 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/menu/portfolio_detail_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 20 | 21 | 28 | 29 | 35 | 36 | 42 | 43 | 48 | 49 | 50 | 51 | --------------------------------------------------------------------------------