├── .github
├── assets
│ ├── Screenshot_1.jpg
│ ├── Screenshot_2.jpg
│ ├── Screenshot_3.jpg
│ ├── Screenshot_4.jpg
│ ├── Screenshot_5.jpg
│ ├── Screenshot_6.jpg
│ ├── favorites.jpg
│ ├── home.jpg
│ ├── manage_accounts.jpg
│ ├── more_info.jpg
│ ├── search.jpg
│ └── viewer.jpg
└── user_deactivation
│ ├── INSTRUCTION.md
│ └── deactivation.jpg
├── .gitignore
├── LICENSE
├── PRIVACY_POLICY.md
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── java
│ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ ├── MainActivity.kt
│ │ ├── MikanseiApp.kt
│ │ ├── MikanseiEnvironment.kt
│ │ ├── MikanseiModule.kt
│ │ └── ui
│ │ ├── MainScreen.kt
│ │ ├── MainViewModel.kt
│ │ ├── appbars
│ │ ├── MainBottomNavigationBar.kt
│ │ ├── MainNavigationItems.kt
│ │ └── MainNavigationRail.kt
│ │ ├── content
│ │ ├── MainContentCompact.kt
│ │ ├── MainContentMediumWide.kt
│ │ └── MainContentResponsive.kt
│ │ ├── core
│ │ └── ShareDownloadDialog.kt
│ │ └── navgraphs
│ │ ├── BottomNavGraph.kt
│ │ └── MainNavGraph.kt
│ └── res
│ ├── drawable
│ ├── ic_launcher_foreground.xml
│ └── ic_launcher_monochrome.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-mdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xhdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── values-night
│ └── themes.xml
│ ├── values-v23
│ └── themes.xml
│ ├── values-v27
│ └── themes.xml
│ ├── values
│ ├── ic_launcher_background.xml
│ └── themes.xml
│ └── xml
│ ├── backup_rules.xml
│ ├── data_extraction_rules.xml
│ └── provider_paths.xml
├── build.gradle
├── core
├── danbooru
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── core
│ │ └── danbooru
│ │ ├── DanbooruApi.kt
│ │ ├── DanbooruModule.kt
│ │ ├── DanbooruRepositoryImpl.kt
│ │ ├── annotation
│ │ ├── NoAuth.kt
│ │ └── NoSafeHost.kt
│ │ ├── interceptor
│ │ ├── DanbooruAuthInterceptor.kt
│ │ ├── DanbooruHostInterceptor.kt
│ │ ├── ForceCacheResponseInterceptor.kt
│ │ ├── ForceLoadFromCacheInterceptor.kt
│ │ ├── ForceRefreshInterceptor.kt
│ │ └── UserDelegationInterceptor.kt
│ │ └── model
│ │ ├── favorite
│ │ ├── DanbooruFavorite.kt
│ │ ├── DanbooruFavoriteGroup.kt
│ │ └── FavoriteMapper.kt
│ │ ├── post
│ │ ├── DanbooruMediaAsset.kt
│ │ ├── DanbooruPost.kt
│ │ ├── DanbooruVariant.kt
│ │ ├── PostMapper.kt
│ │ ├── PostVoteMapper.kt
│ │ └── vote
│ │ │ └── DanbooruPostVote.kt
│ │ ├── profile
│ │ ├── DanbooruProfile.kt
│ │ └── ProfileMapper.kt
│ │ ├── saved_search
│ │ ├── DanbooruSavedSearch.kt
│ │ └── SavedSearchMapper.kt
│ │ ├── tag
│ │ ├── DanbooruTag.kt
│ │ ├── DanbooruTagAutoComplete.kt
│ │ ├── DanbooruTagPayload.kt
│ │ └── TagMapper.kt
│ │ └── user
│ │ ├── DanbooruUser.kt
│ │ ├── UserMapper.kt
│ │ └── field
│ │ ├── DanbooruUserField.kt
│ │ └── DanbooruUserFieldData.kt
├── database
│ ├── .gitignore
│ ├── build.gradle
│ ├── schemas
│ │ └── com.uragiristereo.mikansei.core.database.MikanseiDatabase
│ │ │ ├── 1.json
│ │ │ └── 2.json
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── core
│ │ └── database
│ │ ├── DatabaseConverters.kt
│ │ ├── DatabaseModule.kt
│ │ ├── MikanseiDatabase.kt
│ │ ├── migration
│ │ └── From1To2MigrationSpec.kt
│ │ ├── post
│ │ ├── PostDao.kt
│ │ ├── PostMapper.kt
│ │ ├── PostRepositoryImpl.kt
│ │ └── PostRow.kt
│ │ ├── search_history
│ │ ├── SearchHistoryDao.kt
│ │ └── SearchHistoryRow.kt
│ │ ├── session
│ │ ├── SessionDao.kt
│ │ ├── SessionMapper.kt
│ │ ├── SessionRepositoryImpl.kt
│ │ └── SessionRow.kt
│ │ ├── session_post
│ │ ├── SessionPostDao.kt
│ │ └── SessionPostRow.kt
│ │ ├── tag_category
│ │ ├── TagCategoryDao.kt
│ │ ├── TagCategoryRepositoryImpl.kt
│ │ └── TagCategoryRow.kt
│ │ ├── user
│ │ ├── UserDao.kt
│ │ ├── UserMapper.kt
│ │ ├── UserRepositoryImpl.kt
│ │ └── UserRow.kt
│ │ └── user_delegation
│ │ ├── UserDelegationDao.kt
│ │ ├── UserDelegationRepositoryImpl.kt
│ │ └── UserDelegationRow.kt
├── domain
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── core
│ │ └── domain
│ │ ├── DomainModule.kt
│ │ ├── module
│ │ ├── danbooru
│ │ │ ├── DanbooruRepository.kt
│ │ │ └── entity
│ │ │ │ ├── Favorite.kt
│ │ │ │ ├── FavoriteResult.kt
│ │ │ │ ├── PostVote.kt
│ │ │ │ ├── PostsResult.kt
│ │ │ │ ├── Profile.kt
│ │ │ │ ├── ProfileSettingsField.kt
│ │ │ │ ├── SavedSearch.kt
│ │ │ │ ├── Tag.kt
│ │ │ │ └── User.kt
│ │ ├── database
│ │ │ ├── PostRepository.kt
│ │ │ ├── SessionRepository.kt
│ │ │ ├── TagCategoryRepository.kt
│ │ │ ├── UserDelegationRepository.kt
│ │ │ ├── UserRepository.kt
│ │ │ └── entity
│ │ │ │ └── Session.kt
│ │ ├── network
│ │ │ ├── DownloadBroadcastReceiver.kt
│ │ │ ├── DownloadRepository.kt
│ │ │ ├── NetworkRepository.kt
│ │ │ └── entity
│ │ │ │ ├── DownloadInfo.kt
│ │ │ │ ├── DownloadInstance.kt
│ │ │ │ └── DownloadResource.kt
│ │ └── search
│ │ │ ├── BrowseChipType.kt
│ │ │ └── TagType.kt
│ │ └── usecase
│ │ ├── ConvertFileSizeUseCase.kt
│ │ ├── DeactivateAccountUseCase.kt
│ │ ├── DownloadPostUseCase.kt
│ │ ├── DownloadPostWithNotificationUseCase.kt
│ │ ├── FilterPostsUseCase.kt
│ │ ├── GenerateChipsFromTagsUseCase.kt
│ │ ├── GetCachedFavoriteGroupsUseCase.kt
│ │ ├── GetFavoriteGroupsUseCase.kt
│ │ ├── GetFavoritesAndFavoriteGroupsUseCase.kt
│ │ ├── GetFavoritesUseCase.kt
│ │ ├── GetPostsUseCase.kt
│ │ ├── GetTagsAutoCompleteUseCase.kt
│ │ ├── GetTagsUseCase.kt
│ │ ├── PerformLoginUseCase.kt
│ │ ├── SyncUserSettingsUseCase.kt
│ │ └── UpdateUserSettingsUseCase.kt
├── model
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── core
│ │ └── model
│ │ ├── CacheUtil.kt
│ │ ├── Constants.kt
│ │ ├── Environment.kt
│ │ ├── FileUtil.kt
│ │ ├── UnitConverter.kt
│ │ ├── danbooru
│ │ ├── DanbooruDateSerializer.kt
│ │ ├── DanbooruHost.kt
│ │ ├── Post.kt
│ │ ├── Rating.kt
│ │ └── ShareOption.kt
│ │ ├── preferences
│ │ ├── base
│ │ │ ├── Preference.kt
│ │ │ ├── PreferenceString.kt
│ │ │ └── PreferenceStringRes.kt
│ │ └── user
│ │ │ ├── DetailSizePreference.kt
│ │ │ └── RatingPreference.kt
│ │ └── result
│ │ ├── FailedResponseFormatter.kt
│ │ └── Result.kt
├── network
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── core
│ │ └── network
│ │ ├── DownloadRepositoryImpl.kt
│ │ ├── MikanseiApi.kt
│ │ ├── NetworkModule.kt
│ │ └── NetworkRepositoryImpl.kt
├── preferences
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── core
│ │ └── preferences
│ │ ├── PreferencesRepository.kt
│ │ ├── PreferencesRepositoryImpl.kt
│ │ ├── PreferencesSerializer.kt
│ │ └── model
│ │ ├── LanguagePreference.kt
│ │ ├── Preferences.kt
│ │ ├── ThemePreference.kt
│ │ └── danbooru
│ │ ├── DanbooruHostPreference.kt
│ │ └── DanbooruHostPreferenceItem.kt
├── product
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── core
│ │ └── product
│ │ ├── ProductModule.kt
│ │ ├── component
│ │ ├── ProductAlertDialog.kt
│ │ ├── ProductDialog.kt
│ │ ├── ProductPostPlaceholder.kt
│ │ ├── ProductPullRefreshIndicator.kt
│ │ ├── ProductSetSystemBarsColor.kt
│ │ ├── ProductSystemBarsSpacer.kt
│ │ └── ProductTopAppBar.kt
│ │ ├── preference
│ │ ├── BottomSheetPreference.kt
│ │ ├── DropDownPreference.kt
│ │ ├── LocalIconPadding.kt
│ │ ├── PreferenceCategory.kt
│ │ ├── PreferenceContainer.kt
│ │ ├── RadioPreference.kt
│ │ ├── RegularPreference.kt
│ │ └── SwitchPreference.kt
│ │ ├── shared
│ │ ├── downloadshare
│ │ │ ├── DownloadShareViewModel.kt
│ │ │ ├── DownloadShareViewModelImpl.kt
│ │ │ └── core
│ │ │ │ └── DownloadState.kt
│ │ └── postfavoritevote
│ │ │ ├── PostFavoriteVote.kt
│ │ │ ├── PostFavoriteVoteImpl.kt
│ │ │ └── core
│ │ │ ├── ScoreChips.kt
│ │ │ └── ScoreState.kt
│ │ └── theme
│ │ ├── Color.kt
│ │ ├── Shapes.kt
│ │ ├── Theme.kt
│ │ └── Type.kt
├── resources
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── res
│ │ │ └── values
│ │ │ └── strings.xml
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── res
│ │ ├── drawable
│ │ ├── add.xml
│ │ ├── add_to_photos.xml
│ │ ├── android.xml
│ │ ├── api.xml
│ │ ├── arrow_back.xml
│ │ ├── aspect_ratio.xml
│ │ ├── cached.xml
│ │ ├── check_box.xml
│ │ ├── check_box_outline_blank.xml
│ │ ├── circle_fill.xml
│ │ ├── close.xml
│ │ ├── collections_bookmark.xml
│ │ ├── collections_bookmark_fill.xml
│ │ ├── construction.xml
│ │ ├── content_copy.xml
│ │ ├── contrast.xml
│ │ ├── danbooru.png
│ │ ├── danbooru_logo.webp
│ │ ├── dark_mode.xml
│ │ ├── dark_mode_fill.xml
│ │ ├── delete.xml
│ │ ├── description.xml
│ │ ├── discord_icon.xml
│ │ ├── done.xml
│ │ ├── download.xml
│ │ ├── download_done.xml
│ │ ├── edit.xml
│ │ ├── error.xml
│ │ ├── expand_less.xml
│ │ ├── expand_more.xml
│ │ ├── explore.xml
│ │ ├── explore_fill.xml
│ │ ├── favorite.xml
│ │ ├── favorite_fill.xml
│ │ ├── filter_list.xml
│ │ ├── format_color_fill.xml
│ │ ├── github_icon.xml
│ │ ├── history.xml
│ │ ├── home.xml
│ │ ├── home_fill.xml
│ │ ├── image_not_supported.xml
│ │ ├── info.xml
│ │ ├── label_off.xml
│ │ ├── light_mode.xml
│ │ ├── light_mode_fill.xml
│ │ ├── lightbulb.xml
│ │ ├── link.xml
│ │ ├── login.xml
│ │ ├── menu.xml
│ │ ├── mikansei_logo.xml
│ │ ├── mop.xml
│ │ ├── more_horiz.xml
│ │ ├── more_vert.xml
│ │ ├── no_sound.xml
│ │ ├── north_west.xml
│ │ ├── open_in_browser.xml
│ │ ├── open_in_full.xml
│ │ ├── pause_fill.xml
│ │ ├── photo_library.xml
│ │ ├── photo_library_fill.xml
│ │ ├── play_arrow_fill.xml
│ │ ├── public_globe.xml
│ │ ├── search.xml
│ │ ├── sell.xml
│ │ ├── settings.xml
│ │ ├── settings_account_box.xml
│ │ ├── share.xml
│ │ ├── translate.xml
│ │ ├── undo.xml
│ │ ├── update.xml
│ │ ├── variable_add.xml
│ │ ├── variable_insert.xml
│ │ ├── variable_remove.xml
│ │ ├── visibility_fill.xml
│ │ ├── visibility_off.xml
│ │ ├── visibility_off_fill.xml
│ │ ├── volume_off.xml
│ │ ├── volume_up.xml
│ │ └── vpn_lock.xml
│ │ ├── raw
│ │ └── unsafe_tags.gz
│ │ └── values
│ │ └── strings.xml
└── ui
│ ├── .gitignore
│ ├── build.gradle
│ ├── navigation-rules.pro
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── core
│ │ └── ui
│ │ ├── CompositionLocals.kt
│ │ ├── WindowSize.kt
│ │ ├── animation
│ │ ├── Hold.kt
│ │ └── Translate.kt
│ │ ├── composable
│ │ ├── Banner.kt
│ │ ├── Chips.kt
│ │ ├── ClickableSection.kt
│ │ ├── DimensionSubcomposeLayout.kt
│ │ ├── DragHandle.kt
│ │ ├── NavigationBarSpacer.kt
│ │ ├── NavigationRail.kt
│ │ ├── OverlappingLayout.kt
│ │ ├── OverlineTitle.kt
│ │ ├── PostHeader.kt
│ │ ├── RailScaffold.kt
│ │ ├── Scaffold2.kt
│ │ ├── SectionTitle.kt
│ │ ├── SetSystemBarsColors.kt
│ │ ├── SettingTip.kt
│ │ ├── SettingToggle.kt
│ │ └── SidesGradient.kt
│ │ ├── database
│ │ └── SavedSearchItem.kt
│ │ ├── entity
│ │ ├── ImmutableList.kt
│ │ └── ImmutableWrapper.kt
│ │ ├── extension
│ │ ├── Channel.kt
│ │ ├── Color.kt
│ │ ├── Context.kt
│ │ ├── Modifier.kt
│ │ ├── NavController.kt
│ │ ├── PaddingValues.kt
│ │ ├── String.kt
│ │ ├── Window.kt
│ │ └── WindowInsets.kt
│ │ ├── modalbottomsheet
│ │ ├── Constants.kt
│ │ ├── ModalBottomSheet3.android.kt
│ │ ├── ModalBottomSheet3.kt
│ │ ├── SheetDefaults.kt
│ │ ├── internal
│ │ │ ├── AnchoredDraggable.kt
│ │ │ ├── DragGestureDetectorCopy.kt
│ │ │ ├── InternalMutatorMutex.android.kt
│ │ │ ├── InternalMutatorMutex.kt
│ │ │ ├── MutablePaddingValues.kt
│ │ │ ├── PlatformOptimizedCancellationException.android.kt
│ │ │ └── PredictiveBack.kt
│ │ └── navigator
│ │ │ ├── BottomSheetNavigator.kt
│ │ │ └── BottomSheetNavigatorProvider.kt
│ │ ├── navigation
│ │ ├── HomeRoute.kt
│ │ ├── MainRoute.kt
│ │ ├── NavRoute.kt
│ │ ├── NavTypeMapOf.kt
│ │ ├── SavedSearchesRoute.kt
│ │ ├── SettingsRoute.kt
│ │ └── UserRoute.kt
│ │ ├── shared
│ │ └── SharedViewModel.kt
│ │ └── view
│ │ └── SelectionAwareEditText.kt
│ └── res
│ └── values
│ └── styles.xml
├── feature
├── about
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── about
│ │ ├── AboutModule.kt
│ │ ├── AboutScreen.kt
│ │ ├── AboutViewModel.kt
│ │ ├── contibutor
│ │ └── ContributorItem.kt
│ │ ├── data
│ │ ├── AboutRepositoryImpl.kt
│ │ ├── GitHubApi.kt
│ │ └── model
│ │ │ └── contributor
│ │ │ ├── GitHubContributorMapper.kt
│ │ │ └── GitHubContributorResponse.kt
│ │ └── domain
│ │ ├── AboutRepository.kt
│ │ └── entity
│ │ └── GitHubContributor.kt
├── filters
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── filters
│ │ ├── FiltersScreen.kt
│ │ ├── FiltersViewModel.kt
│ │ ├── appbars
│ │ └── FiltersTopAppBar.kt
│ │ ├── column
│ │ ├── FilterItem.kt
│ │ ├── FiltersColumn.kt
│ │ └── FiltersColumnItem.kt
│ │ └── core
│ │ ├── FiltersAddTagsDialog.kt
│ │ ├── FiltersFab.kt
│ │ ├── FiltersModalBottomSheet.kt
│ │ └── FiltersNavigation.kt
├── home
│ ├── .gitignore
│ ├── build.gradle
│ ├── favorites
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── com
│ │ │ └── uragiristereo
│ │ │ └── mikansei
│ │ │ └── feature
│ │ │ └── home
│ │ │ └── favorites
│ │ │ ├── FavoritesModule.kt
│ │ │ ├── FavoritesScreen.kt
│ │ │ ├── FavoritesViewModel.kt
│ │ │ ├── core
│ │ │ ├── FavoritesTopAppBar.kt
│ │ │ ├── LoadingIndicator.kt
│ │ │ └── LoadingState.kt
│ │ │ ├── favgroup
│ │ │ ├── addto
│ │ │ │ ├── AddToFavGroupContent.kt
│ │ │ │ ├── AddToFavGroupViewModel.kt
│ │ │ │ ├── column
│ │ │ │ │ ├── FavoriteGroupItem.kt
│ │ │ │ │ └── FavoriteGroupsColumn.kt
│ │ │ │ └── core
│ │ │ │ │ ├── CreateNewFavGroupButton.kt
│ │ │ │ │ └── FavoriteGroup.kt
│ │ │ ├── delete
│ │ │ │ └── DeleteFavGroupContent.kt
│ │ │ ├── edit
│ │ │ │ ├── EditFavGroupScreen.kt
│ │ │ │ ├── EditFavGroupViewModel.kt
│ │ │ │ └── core
│ │ │ │ │ ├── EditFavGroupTopAppBar.kt
│ │ │ │ │ └── UnsavedConfirmationDialog.kt
│ │ │ ├── more
│ │ │ │ ├── FavGroupMoreContent.kt
│ │ │ │ └── FavGroupMoreViewModel.kt
│ │ │ └── new
│ │ │ │ ├── NewFavGroupScreen.kt
│ │ │ │ ├── NewFavGroupViewModel.kt
│ │ │ │ └── core
│ │ │ │ ├── FabState.kt
│ │ │ │ ├── LoadingFab.kt
│ │ │ │ ├── NewFavGroupFab.kt
│ │ │ │ ├── NewFavGroupTopAppBar.kt
│ │ │ │ └── SubmitFab.kt
│ │ │ └── grid
│ │ │ ├── FavoriteItem.kt
│ │ │ └── FavoritesGrid.kt
│ ├── more
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── com
│ │ │ └── uragiristereo
│ │ │ └── mikansei
│ │ │ └── feature
│ │ │ └── home
│ │ │ └── more
│ │ │ ├── MoreScreen.kt
│ │ │ ├── MoreViewModel.kt
│ │ │ └── core
│ │ │ ├── MoreNavigation.kt
│ │ │ ├── MoreTopAppBar.kt
│ │ │ ├── NavigationItem.kt
│ │ │ └── UserHeader.kt
│ ├── posts
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── com
│ │ │ └── uragiristereo
│ │ │ └── mikansei
│ │ │ └── feature
│ │ │ └── home
│ │ │ └── posts
│ │ │ ├── PostsScreen.kt
│ │ │ ├── PostsViewModel.kt
│ │ │ ├── core
│ │ │ ├── PostsNavigation.kt
│ │ │ └── PostsTopAppBar.kt
│ │ │ ├── grid
│ │ │ ├── PostBorder.kt
│ │ │ ├── PostItem.kt
│ │ │ ├── PostLabel.kt
│ │ │ ├── PostPlaceholder.kt
│ │ │ └── PostsGrid.kt
│ │ │ ├── more
│ │ │ ├── PostMoreContent.kt
│ │ │ ├── PostMoreViewModel.kt
│ │ │ └── core
│ │ │ │ ├── FavoriteSection.kt
│ │ │ │ └── ScoreSection.kt
│ │ │ ├── share
│ │ │ ├── ShareContent.kt
│ │ │ └── ShareViewModel.kt
│ │ │ └── state
│ │ │ ├── PostsContentState.kt
│ │ │ ├── PostsEmpty.kt
│ │ │ ├── PostsError.kt
│ │ │ ├── PostsLoadingState.kt
│ │ │ └── PostsProgress.kt
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── home
│ │ ├── HomeModule.kt
│ │ └── HomeNavigation.kt
├── image
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── image
│ │ ├── ImageModule.kt
│ │ ├── ImageScreen.kt
│ │ ├── ViewerViewModel.kt
│ │ ├── core
│ │ ├── DownloadShareRow.kt
│ │ ├── ImageNavigation.kt
│ │ ├── ModifierExt.kt
│ │ └── ViewerTopAppBar.kt
│ │ ├── image
│ │ ├── ImagePost.kt
│ │ ├── ImageViewModel.kt
│ │ ├── ImageViewer.kt
│ │ ├── UnsupportedPost.kt
│ │ ├── appbars
│ │ │ ├── ImageBottomAppBar.kt
│ │ │ └── ImageTopAppBar.kt
│ │ └── core
│ │ │ └── ImageLoadingState.kt
│ │ ├── more
│ │ ├── MoreBottomSheet.kt
│ │ ├── MoreBottomSheetViewModel.kt
│ │ ├── core
│ │ │ ├── MoreActionsRow.kt
│ │ │ ├── MoreCloseButton.kt
│ │ │ ├── MoreDate.kt
│ │ │ ├── MoreSource.kt
│ │ │ └── MoreTagsButton.kt
│ │ ├── info
│ │ │ ├── MoreInfo.kt
│ │ │ ├── MoreInfoButton.kt
│ │ │ └── MoreInfoColumn.kt
│ │ └── tags
│ │ │ ├── MoreTagItem.kt
│ │ │ ├── MoreTagsRow.kt
│ │ │ └── TagActionsBottomSheet.kt
│ │ └── video
│ │ ├── VideoPlayer.kt
│ │ ├── VideoPost.kt
│ │ ├── VideoTopAppBar.kt
│ │ ├── VideoViewModel.kt
│ │ └── controls
│ │ ├── ControlSlider.kt
│ │ ├── PlayPauseButton.kt
│ │ ├── SoundButton.kt
│ │ ├── TimeInfo.kt
│ │ └── VideoControls.kt
├── saved_searches
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── saved_searches
│ │ ├── SavedSearchesModule.kt
│ │ ├── SavedSearchesScreen.kt
│ │ ├── SavedSearchesViewModel.kt
│ │ ├── core
│ │ └── SavedSearchesTopAppBar.kt
│ │ ├── delete
│ │ └── DeleteSavedSearchContent.kt
│ │ ├── list
│ │ ├── SavedSearchesList.kt
│ │ ├── SavedSearchesListItem.kt
│ │ └── SavedSearchesListItemActions.kt
│ │ └── new_or_edit
│ │ ├── NewOrEditSavedSearchScreen.kt
│ │ ├── NewOrEditSavedSearchViewModel.kt
│ │ └── core
│ │ ├── FabState.kt
│ │ ├── LoadingFab.kt
│ │ ├── NewOrEditSavedSearchFab.kt
│ │ ├── NewOrEditSavedSearchTopAppBar.kt
│ │ ├── SubmitFab.kt
│ │ └── UnsavedConfirmationDialog.kt
├── search
│ ├── .gitignore
│ ├── build.gradle
│ ├── mock
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── main
│ │ │ └── java
│ │ │ └── com
│ │ │ └── uragiristereo
│ │ │ └── mikansei
│ │ │ └── feature
│ │ │ └── search
│ │ │ └── mock
│ │ │ └── BrowseChipsMock.kt
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── uragiristereo
│ │ │ └── mikansei
│ │ │ └── feature
│ │ │ └── search
│ │ │ └── BrowseChipsPreview.kt
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── uragiristereo
│ │ │ └── mikansei
│ │ │ └── feature
│ │ │ └── search
│ │ │ ├── SearchScreen.kt
│ │ │ ├── SearchViewModel.kt
│ │ │ ├── browse_chips
│ │ │ └── BrowseChips.kt
│ │ │ ├── core
│ │ │ ├── SearchBar.kt
│ │ │ └── SearchNavigation.kt
│ │ │ ├── quick_shortcut_bar
│ │ │ ├── SearchQuickShortcutBar.kt
│ │ │ └── SearchQuickShortcutBarItem.kt
│ │ │ ├── result
│ │ │ └── SearchResultItem.kt
│ │ │ └── state
│ │ │ └── SearchWordIndex.kt
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── search
│ │ └── BrowseChipsTest.kt
├── settings
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── settings
│ │ ├── SettingsColumn.kt
│ │ ├── SettingsScreen.kt
│ │ ├── SettingsViewModel.kt
│ │ └── core
│ │ ├── SettingsNavigation.kt
│ │ └── SettingsTopAppBar.kt
└── user
│ ├── .gitignore
│ ├── build.gradle
│ ├── deactivation
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── user
│ │ └── deactivation
│ │ ├── UserDeactivationScreen.kt
│ │ ├── UserDeactivationViewModel.kt
│ │ ├── agreement
│ │ └── UserDeactivationAgreementScreen.kt
│ │ ├── core
│ │ ├── UserDeactivationNavigation.kt
│ │ └── UserDeactivationTopAppBar.kt
│ │ ├── in_app
│ │ ├── UserDeactivationInAppConfirmationDialog.kt
│ │ └── UserDeactivationInAppScreen.kt
│ │ ├── in_web
│ │ └── UserDeactivationInWebScreen.kt
│ │ ├── methods
│ │ └── UserDeactivationMethodsScreen.kt
│ │ └── navigation
│ │ ├── UserDeactivationNavGraph.kt
│ │ └── UserDeactivationRoute.kt
│ ├── delegation
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── user
│ │ └── delegation
│ │ ├── UserDelegationSettingsScreen.kt
│ │ ├── UserDelegationSettingsViewModel.kt
│ │ ├── core
│ │ ├── UserDelegationSettingsNavigation.kt
│ │ └── UserDelegationTopAppBar.kt
│ │ └── list
│ │ ├── UserDelegation.kt
│ │ ├── UserDelegationList.kt
│ │ └── UserDelegationListItem.kt
│ ├── login
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── user
│ │ └── login
│ │ ├── LoginScreen.kt
│ │ ├── LoginViewModel.kt
│ │ ├── core
│ │ ├── DanbooruLogo.kt
│ │ └── LoginNavigation.kt
│ │ └── dialog
│ │ ├── LoginDialog.kt
│ │ └── LoginState.kt
│ ├── manage
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── user
│ │ └── manage
│ │ ├── ManageUserScreen.kt
│ │ ├── ManageUserViewModel.kt
│ │ ├── core
│ │ ├── ManageNavigation.kt
│ │ ├── ProfileDropDownMenu.kt
│ │ ├── ProfileItem.kt
│ │ └── UsersState.kt
│ │ └── switch_account
│ │ ├── SwitchAccountContent.kt
│ │ └── SwitchAccountProfileItem.kt
│ ├── settings
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── uragiristereo
│ │ └── mikansei
│ │ └── feature
│ │ └── user
│ │ └── settings
│ │ ├── UserSettingsScreen.kt
│ │ ├── UserSettingsViewModel.kt
│ │ └── core
│ │ ├── UserSettingsNavigation.kt
│ │ └── UserSettingsTopAppBar.kt
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── uragiristereo
│ └── mikansei
│ └── feature
│ └── user
│ ├── UserModule.kt
│ └── UserNavigation.kt
├── gradle.properties
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.github/assets/Screenshot_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/Screenshot_1.jpg
--------------------------------------------------------------------------------
/.github/assets/Screenshot_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/Screenshot_2.jpg
--------------------------------------------------------------------------------
/.github/assets/Screenshot_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/Screenshot_3.jpg
--------------------------------------------------------------------------------
/.github/assets/Screenshot_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/Screenshot_4.jpg
--------------------------------------------------------------------------------
/.github/assets/Screenshot_5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/Screenshot_5.jpg
--------------------------------------------------------------------------------
/.github/assets/Screenshot_6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/Screenshot_6.jpg
--------------------------------------------------------------------------------
/.github/assets/favorites.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/favorites.jpg
--------------------------------------------------------------------------------
/.github/assets/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/home.jpg
--------------------------------------------------------------------------------
/.github/assets/manage_accounts.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/manage_accounts.jpg
--------------------------------------------------------------------------------
/.github/assets/more_info.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/more_info.jpg
--------------------------------------------------------------------------------
/.github/assets/search.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/search.jpg
--------------------------------------------------------------------------------
/.github/assets/viewer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/assets/viewer.jpg
--------------------------------------------------------------------------------
/.github/user_deactivation/deactivation.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/.github/user_deactivation/deactivation.jpg
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | *.log
4 | /local.properties
5 | /.idea/caches
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | /.idea/navEditor.xml
10 | /.idea/assetWizardSettings.xml
11 | .DS_Store
12 | /build
13 | /captures
14 | .externalNativeBuild
15 | .cxx
16 | local.properties
17 | /signing.properties
18 | /.idea/
19 | /.kotlin/
20 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /release/
3 | /debug/
4 | google-services.json
5 | /oss/
6 | /play/
7 |
--------------------------------------------------------------------------------
/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 |
23 | #-keepnames class **
24 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/com/uragiristereo/mikansei/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
7 | import androidx.core.view.WindowCompat
8 | import com.uragiristereo.mikansei.ui.MainScreen
9 | import org.koin.compose.KoinContext
10 |
11 |
12 | class MainActivity : ComponentActivity() {
13 | override fun onCreate(savedInstanceState: Bundle?) {
14 | super.onCreate(savedInstanceState)
15 |
16 | installSplashScreen()
17 |
18 | WindowCompat.setDecorFitsSystemWindows(window, false)
19 |
20 | setContent {
21 | KoinContext {
22 | MainScreen()
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uragiristereo/mikansei/MikanseiEnvironment.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei
2 |
3 | import com.uragiristereo.mikansei.core.model.Environment
4 |
5 | class MikanseiEnvironment : Environment {
6 | private val safeFlavors = listOf(
7 | Environment.Flavor.PLAY,
8 | )
9 |
10 | override val debug = BuildConfig.DEBUG
11 | override val flavor = Environment.Flavor.getByName(BuildConfig.FLAVOR)
12 | override val safeMode = flavor in safeFlavors
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/uragiristereo/mikansei/ui/navgraphs/BottomNavGraph.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.ui.navgraphs
2 |
3 | import androidx.navigation.NavGraphBuilder
4 | import androidx.navigation.NavHostController
5 | import com.uragiristereo.mikansei.feature.home.favorites.favoritesBottomRoute
6 | import com.uragiristereo.mikansei.feature.home.posts.core.postsBottomRoute
7 | import com.uragiristereo.mikansei.feature.image.core.imageBottomRoute
8 | import com.uragiristereo.mikansei.feature.saved_searches.savedSearchesBottomRoute
9 | import com.uragiristereo.mikansei.feature.user.manage.core.manageBottomRoute
10 |
11 | fun NavGraphBuilder.bottomNavGraph(
12 | mainNavController: NavHostController,
13 | ) {
14 | postsBottomRoute(mainNavController)
15 |
16 | manageBottomRoute(mainNavController)
17 |
18 | favoritesBottomRoute(mainNavController)
19 |
20 | savedSearchesBottomRoute(mainNavController)
21 |
22 | imageBottomRoute(mainNavController)
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/uragiristereo/Mikansei/5a7308c1da542bd8822213350a7520838cf75479/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v27/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.android.application) apply false
3 | alias(libs.plugins.android.library) apply false
4 | alias(libs.plugins.kotlin.android) apply false
5 | alias(libs.plugins.kotlin.parcelize) apply false
6 | alias(libs.plugins.gms) apply false
7 | alias(libs.plugins.firebase.crashlytics) apply false
8 | alias(libs.plugins.compose.compiler) apply false
9 | }
10 |
11 | tasks.register('clean', Delete) {
12 | delete rootProject.layout.buildDirectory
13 | }
14 |
--------------------------------------------------------------------------------
/core/danbooru/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/core/danbooru/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.android.library)
3 | alias(libs.plugins.kotlin.android)
4 | alias(libs.plugins.kotlinx.serialization)
5 | }
6 |
7 | android {
8 | namespace "com.uragiristereo.mikansei.core.danbooru"
9 |
10 | compileOptions {
11 | coreLibraryDesugaringEnabled true
12 | }
13 | }
14 |
15 | kotlin {
16 | jvmToolchain(17)
17 | }
18 |
19 | dependencies {
20 | implementation(project(":core:domain"))
21 | implementation(project(":core:model"))
22 | implementation(project(":core:network"))
23 | implementation(project(":core:preferences"))
24 | implementation(project(":core:resources"))
25 |
26 | implementation(libs.bundles.core)
27 | implementation(libs.bundles.retrofit)
28 | implementation(libs.kotlinx.serialization.json)
29 | coreLibraryDesugaring(libs.desugar.jdk.libs)
30 | }
31 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/DanbooruModule.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru
2 |
3 | import com.uragiristereo.mikansei.core.danbooru.interceptor.DanbooruAuthInterceptor
4 | import com.uragiristereo.mikansei.core.danbooru.interceptor.DanbooruHostInterceptor
5 | import com.uragiristereo.mikansei.core.danbooru.interceptor.ForceLoadFromCacheInterceptor
6 | import com.uragiristereo.mikansei.core.danbooru.interceptor.UserDelegationInterceptor
7 | import com.uragiristereo.mikansei.core.domain.module.danbooru.DanbooruRepository
8 | import org.koin.core.module.dsl.singleOf
9 | import org.koin.dsl.bind
10 | import org.koin.dsl.module
11 |
12 | val danbooruModule = module {
13 | singleOf(::DanbooruRepositoryImpl) bind DanbooruRepository::class
14 | singleOf(::DanbooruAuthInterceptor)
15 | singleOf(::DanbooruHostInterceptor)
16 | singleOf(::UserDelegationInterceptor)
17 | singleOf(::ForceLoadFromCacheInterceptor)
18 | }
19 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/annotation/NoAuth.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.annotation
2 |
3 | annotation class NoAuth
4 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/annotation/NoSafeHost.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.annotation
2 |
3 | annotation class NoSafeHost
4 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/interceptor/ForceRefreshInterceptor.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.interceptor
2 |
3 | import okhttp3.CacheControl
4 | import okhttp3.Interceptor
5 | import okhttp3.Response
6 |
7 | object ForceRefreshInterceptor : Interceptor {
8 | override fun intercept(chain: Interceptor.Chain): Response {
9 | val request = chain.request()
10 | val isForceRefresh = request.headers["force-refresh"]?.toBoolean() ?: false
11 |
12 | if (isForceRefresh) {
13 | val forceRefreshRequest = request
14 | .newBuilder()
15 | .removeHeader("force-refresh")
16 | .cacheControl(CacheControl.Builder().noCache().build())
17 | .build()
18 |
19 | return chain.proceed(forceRefreshRequest)
20 | }
21 |
22 | return chain.proceed(request)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/favorite/DanbooruFavorite.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.favorite
2 |
3 |
4 | import kotlinx.serialization.SerialName
5 | import kotlinx.serialization.Serializable
6 |
7 | @Serializable
8 | data class DanbooruFavorite(
9 | @SerialName("id")
10 | val id: Int,
11 |
12 | @SerialName("user_id")
13 | val userId: Int,
14 |
15 | @SerialName("post_id")
16 | val postId: Int,
17 | )
18 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/favorite/DanbooruFavoriteGroup.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.favorite
2 |
3 |
4 | import com.uragiristereo.mikansei.core.model.danbooru.DanbooruDateSerializer
5 | import kotlinx.serialization.SerialName
6 | import kotlinx.serialization.Serializable
7 | import java.time.OffsetDateTime
8 |
9 | @Serializable
10 | data class DanbooruFavoriteGroup(
11 | @SerialName("id")
12 | val id: Int,
13 |
14 | @SerialName("name")
15 | val name: String,
16 |
17 | @SerialName("creator_id")
18 | val creatorId: Int,
19 |
20 | @SerialName("post_ids")
21 | val postIds: List,
22 |
23 | @SerialName("created_at")
24 | @Serializable(DanbooruDateSerializer::class)
25 | val createdAt: OffsetDateTime,
26 |
27 | @SerialName("updated_at")
28 | @Serializable(DanbooruDateSerializer::class)
29 | val updatedAt: OffsetDateTime,
30 |
31 | @SerialName("is_public")
32 | val isPublic: Boolean,
33 | )
34 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/favorite/FavoriteMapper.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.favorite
2 |
3 | import com.uragiristereo.mikansei.core.domain.module.danbooru.entity.Favorite
4 |
5 | fun DanbooruFavoriteGroup.toFavorite(): Favorite {
6 | return Favorite(
7 | id = id,
8 | name = name.replace(oldChar = '_', newChar = ' '),
9 | thumbnailUrl = null,
10 | postIds = postIds,
11 | )
12 | }
13 |
14 | fun List.toFavoriteList(): List {
15 | return map { it.toFavorite() }
16 | }
17 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/post/DanbooruMediaAsset.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.post
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class DanbooruMediaAsset(
8 | @SerialName("variants")
9 | val variants: List?,
10 | )
11 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/post/DanbooruVariant.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.post
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class DanbooruVariant(
8 | @SerialName("type")
9 | val type: String,
10 |
11 | @SerialName("url")
12 | val url: String,
13 |
14 | @SerialName("width")
15 | val width: Int,
16 |
17 | @SerialName("height")
18 | val height: Int,
19 |
20 | @SerialName("file_ext")
21 | val fileExt: String,
22 | )
23 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/post/PostVoteMapper.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.post
2 |
3 | import com.uragiristereo.mikansei.core.danbooru.model.post.vote.DanbooruPostVote
4 | import com.uragiristereo.mikansei.core.domain.module.danbooru.entity.PostVote
5 |
6 | fun List.toPostVote(
7 | postId: Int,
8 | userId: Int,
9 | ): PostVote {
10 | val postVote = firstOrNull { it.postId == postId && it.userId == userId }
11 |
12 | return PostVote(
13 | postId = postId,
14 | userId = userId,
15 | status = when {
16 | postVote == null -> PostVote.Status.NONE
17 | postVote.score == 1 -> PostVote.Status.UPVOTED
18 | else -> PostVote.Status.DOWNVOTED
19 | },
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/post/vote/DanbooruPostVote.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.post.vote
2 |
3 | import com.uragiristereo.mikansei.core.model.danbooru.DanbooruDateSerializer
4 | import kotlinx.serialization.SerialName
5 | import kotlinx.serialization.Serializable
6 | import java.time.OffsetDateTime
7 |
8 | @Serializable
9 | data class DanbooruPostVote(
10 | @SerialName("id")
11 | val id: Int,
12 |
13 | @SerialName("post_id")
14 | val postId: Int,
15 |
16 | @SerialName("user_id")
17 | val userId: Int,
18 |
19 | @SerialName("created_at")
20 | @Serializable(DanbooruDateSerializer::class)
21 | val createdAt: OffsetDateTime,
22 |
23 | @SerialName("updated_at")
24 | @Serializable(DanbooruDateSerializer::class)
25 | val updatedAt: OffsetDateTime,
26 |
27 | @SerialName("score")
28 | val score: Int,
29 |
30 | @SerialName("is_deleted")
31 | val isDeleted: Boolean,
32 | )
33 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/profile/ProfileMapper.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.profile
2 |
3 | import com.uragiristereo.mikansei.core.domain.module.danbooru.entity.Profile
4 | import com.uragiristereo.mikansei.core.model.preferences.user.DetailSizePreference
5 | import com.uragiristereo.mikansei.core.model.preferences.user.getEnumFromDanbooru
6 |
7 | fun DanbooruProfile.toProfile(): Profile {
8 | return Profile(
9 | id = id,
10 | name = name,
11 | level = Profile.Level.getLevelById(level),
12 | danbooru = Profile.DanbooruSettings(
13 | safeMode = enableSafeMode,
14 | showDeletedPosts = showDeletedPosts,
15 | defaultImageSize = DetailSizePreference.entries.getEnumFromDanbooru(defaultImageSize),
16 | blacklistedTags = when {
17 | blacklistedTags.isNotBlank() -> blacklistedTags.split("\n").distinct()
18 | else -> listOf()
19 | },
20 | ),
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/saved_search/DanbooruSavedSearch.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.saved_search
2 |
3 | import com.uragiristereo.mikansei.core.model.danbooru.DanbooruDateSerializer
4 | import kotlinx.serialization.SerialName
5 | import kotlinx.serialization.Serializable
6 | import java.time.OffsetDateTime
7 |
8 | @Serializable
9 | data class DanbooruSavedSearch(
10 | @SerialName("id")
11 | val id: Int,
12 |
13 | @SerialName("user_id")
14 | val userId: Int,
15 |
16 | @SerialName("query")
17 | val query: String,
18 |
19 | @SerialName("created_at")
20 | @Serializable(DanbooruDateSerializer::class)
21 | val createdAt: OffsetDateTime,
22 |
23 | @SerialName("updated_at")
24 | @Serializable(DanbooruDateSerializer::class)
25 | val updatedAt: OffsetDateTime,
26 |
27 | @SerialName("labels")
28 | val labels: List,
29 | )
30 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/saved_search/SavedSearchMapper.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.saved_search
2 |
3 | import com.uragiristereo.mikansei.core.domain.module.danbooru.entity.SavedSearch
4 |
5 | fun DanbooruSavedSearch.toSavedSearch(): SavedSearch {
6 | return SavedSearch(
7 | id = id,
8 | query = query,
9 | labels = labels,
10 | )
11 | }
12 |
13 | fun List.toSavedSearchList(): List {
14 | return map {
15 | it.toSavedSearch()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/tag/DanbooruTag.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.tag
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class DanbooruTag(
8 | @SerialName("id")
9 | val id: Int,
10 |
11 | @SerialName("name")
12 | val name: String,
13 |
14 | @SerialName("post_count")
15 | val postCount: Long,
16 |
17 | @SerialName("category")
18 | val category: Int,
19 |
20 | @SerialName("created_at")
21 | val createdAt: String,
22 |
23 | @SerialName("updated_at")
24 | val updatedAt: String,
25 |
26 | @SerialName("is_deprecated")
27 | val isDeprecated: Boolean,
28 |
29 | @SerialName("words")
30 | val words: List,
31 | )
32 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/tag/DanbooruTagAutoComplete.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.tag
2 |
3 |
4 | import kotlinx.serialization.SerialName
5 | import kotlinx.serialization.Serializable
6 |
7 | @Serializable
8 | data class DanbooruTagAutoComplete(
9 | @SerialName("type")
10 | val type: String,
11 |
12 | @SerialName("label")
13 | val label: String,
14 |
15 | @SerialName("value")
16 | val value: String,
17 |
18 | @SerialName("category")
19 | val category: Int? = null,
20 |
21 | @SerialName("post_count")
22 | val postCount: Long? = null,
23 |
24 | @SerialName("antecedent")
25 | val antecedent: String? = null,
26 | )
27 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/tag/DanbooruTagPayload.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.tag
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class DanbooruTagPayload(
8 | @SerialName("search")
9 | val search: Search,
10 | ) {
11 | @Serializable
12 | data class Search(
13 | @SerialName("name")
14 | val name: List,
15 | )
16 |
17 | companion object {
18 | fun create(tags: List): DanbooruTagPayload {
19 | return DanbooruTagPayload(
20 | Search(name = tags)
21 | )
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/user/UserMapper.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.user
2 |
3 | import com.uragiristereo.mikansei.core.domain.module.danbooru.entity.Profile
4 | import com.uragiristereo.mikansei.core.domain.module.danbooru.entity.User
5 |
6 | fun DanbooruUser.toUser(): User {
7 | return User(
8 | id = id,
9 | name = name,
10 | level = Profile.Level.getLevelById(level),
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/user/field/DanbooruUserField.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.user.field
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class DanbooruUserField(
8 | @SerialName("user")
9 | val user: DanbooruUserFieldData,
10 | )
11 |
--------------------------------------------------------------------------------
/core/danbooru/src/main/java/com/uragiristereo/mikansei/core/danbooru/model/user/field/DanbooruUserFieldData.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.danbooru.model.user.field
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class DanbooruUserFieldData(
8 | @SerialName("enable_safe_mode")
9 | val enableSafeMode: Boolean? = null,
10 |
11 | @SerialName("show_deleted_posts")
12 | val showDeletedPosts: Boolean? = null,
13 |
14 | @SerialName("default_image_size")
15 | val defaultImageSize: String? = null,
16 |
17 | @SerialName("blacklisted_tags")
18 | val blacklistedTags: String? = null,
19 | )
20 |
--------------------------------------------------------------------------------
/core/database/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/core/database/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.android.library)
3 | alias(libs.plugins.kotlin.android)
4 | alias(libs.plugins.ksp)
5 | }
6 |
7 | android {
8 | namespace "com.uragiristereo.mikansei.core.database"
9 |
10 | compileOptions {
11 | coreLibraryDesugaringEnabled true
12 | }
13 |
14 | ksp {
15 | arg("room.schemaLocation", "$projectDir/schemas")
16 | }
17 | }
18 |
19 | kotlin {
20 | jvmToolchain(17)
21 | }
22 |
23 | dependencies {
24 | implementation(project(":core:domain"))
25 | implementation(project(":core:model"))
26 | implementation(project(":core:preferences"))
27 | implementation(project(":core:ui"))
28 |
29 | implementation(libs.bundles.core)
30 | implementation(libs.bundles.room)
31 | ksp(libs.room.compiler)
32 | implementation(libs.kotlinx.serialization.json)
33 | coreLibraryDesugaring(libs.desugar.jdk.libs)
34 | }
35 |
--------------------------------------------------------------------------------
/core/database/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/migration/From1To2MigrationSpec.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.migration
2 |
3 | import androidx.room.DeleteTable
4 | import androidx.room.migration.AutoMigrationSpec
5 |
6 | @DeleteTable(tableName = "sessions")
7 | class From1To2MigrationSpec : AutoMigrationSpec
8 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/post/PostMapper.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.post
2 |
3 | import com.uragiristereo.mikansei.core.model.danbooru.Post
4 |
5 | fun Post.toPostRow(): PostRow {
6 | return PostRow(
7 | id = id,
8 | data = this,
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/post/PostRepositoryImpl.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.post
2 |
3 | import com.uragiristereo.mikansei.core.domain.module.database.PostRepository
4 | import com.uragiristereo.mikansei.core.model.danbooru.Post
5 | import kotlinx.coroutines.flow.Flow
6 |
7 | class PostRepositoryImpl(private val postDao: PostDao) : PostRepository {
8 | override fun getUploaderName(postId: Int): Flow {
9 | return postDao.getUploaderName(postId)
10 | }
11 |
12 | override suspend fun update(post: Post) {
13 | postDao.update(postId = post.id, post = post)
14 | }
15 |
16 | override suspend fun update(posts: List) {
17 | postDao.update(posts)
18 | }
19 |
20 | override suspend fun updateUploaderName(postId: Int, uploaderName: String) {
21 | postDao.updateUploaderName(postId = postId, uploaderName = uploaderName)
22 | }
23 |
24 | override suspend fun reset() {
25 | postDao.reset()
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/post/PostRow.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.post
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 | import com.uragiristereo.mikansei.core.model.danbooru.Post
7 | import java.time.OffsetDateTime
8 |
9 | @Entity(tableName = "posts")
10 | data class PostRow(
11 | @PrimaryKey
12 | @ColumnInfo(name = "post_id")
13 | val id: Int,
14 |
15 | @ColumnInfo(name = "data")
16 | val data: Post,
17 |
18 | @ColumnInfo(name = "uploader_name", defaultValue = "null")
19 | val uploaderName: String? = null,
20 |
21 | @ColumnInfo(name = "updated_at")
22 | val updatedAt: OffsetDateTime = OffsetDateTime.now(),
23 | )
24 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/search_history/SearchHistoryDao.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.search_history
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Delete
5 | import androidx.room.Insert
6 | import androidx.room.Query
7 | import kotlinx.coroutines.flow.Flow
8 |
9 | @Dao
10 | interface SearchHistoryDao {
11 | @Query("select * from search_history order by date desc")
12 | fun getAll(): Flow>
13 |
14 | @Insert
15 | suspend fun add(item: SearchHistoryRow)
16 |
17 | @Delete
18 | suspend fun delete(items: List)
19 |
20 | @Query("delete from search_history")
21 | suspend fun clear()
22 | }
23 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/search_history/SearchHistoryRow.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.search_history
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import java.time.OffsetDateTime
6 |
7 | @Entity(tableName = "search_history")
8 | data class SearchHistoryRow(
9 | @PrimaryKey val uuid: String,
10 | val tags: String,
11 | val date: OffsetDateTime,
12 | )
13 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/session/SessionDao.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.session
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy
6 | import androidx.room.Query
7 | import androidx.room.Upsert
8 | import kotlinx.coroutines.flow.Flow
9 |
10 | @Dao
11 | interface SessionDao {
12 | @Query("select * from sessions_v2 where session_id = :sessionId")
13 | fun get(sessionId: String): Flow
14 |
15 | @Insert(onConflict = OnConflictStrategy.IGNORE)
16 | suspend fun add(sessionRow: SessionRow)
17 |
18 | @Upsert
19 | suspend fun update(sessionRow: SessionRow)
20 |
21 | @Query("delete from sessions_v2 where session_id = :sessionId")
22 | suspend fun delete(sessionId: String)
23 |
24 | @Query("delete from sessions_v2")
25 | suspend fun reset()
26 | }
27 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/session/SessionMapper.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.session
2 |
3 | import com.uragiristereo.mikansei.core.domain.module.database.entity.Session
4 |
5 | fun SessionRow.toSession(): Session {
6 | return Session(
7 | id = id,
8 | tags = tags,
9 | scrollIndex = scrollIndex,
10 | scrollOffset = scrollOffset,
11 | )
12 | }
13 |
14 | fun Session.toSessionRow(): SessionRow {
15 | return SessionRow(
16 | id = id,
17 | tags = tags,
18 | scrollIndex = scrollIndex,
19 | scrollOffset = scrollOffset,
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/session/SessionRow.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.session
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 |
7 | @Entity(tableName = "sessions_v2")
8 | data class SessionRow(
9 | @PrimaryKey
10 | @ColumnInfo(name = "session_id")
11 | val id: String,
12 |
13 | @ColumnInfo(name = "tags")
14 | val tags: String,
15 |
16 | @ColumnInfo(name = "scroll_index", defaultValue = "0")
17 | val scrollIndex: Int = 0,
18 |
19 | @ColumnInfo(name = "scroll_offset", defaultValue = "0")
20 | val scrollOffset: Int = 0,
21 | )
22 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/tag_category/TagCategoryDao.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.tag_category
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Query
5 | import androidx.room.Upsert
6 | import kotlinx.coroutines.flow.Flow
7 |
8 | @Dao
9 | interface TagCategoryDao {
10 | @Query("select * from tag_categories where tag in (:tags)")
11 | fun getCategories(tags: List): Flow>
12 |
13 | @Upsert
14 | suspend fun update(tags: List)
15 | }
16 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/uragiristereo/mikansei/core/database/tag_category/TagCategoryRepositoryImpl.kt:
--------------------------------------------------------------------------------
1 | package com.uragiristereo.mikansei.core.database.tag_category
2 |
3 | import com.uragiristereo.mikansei.core.domain.module.danbooru.entity.Tag
4 | import com.uragiristereo.mikansei.core.domain.module.database.TagCategoryRepository
5 | import kotlinx.coroutines.flow.Flow
6 | import kotlinx.coroutines.flow.map
7 |
8 | class TagCategoryRepositoryImpl(
9 | private val tagCategoryDao: TagCategoryDao,
10 | ) : TagCategoryRepository {
11 | override fun getCategories(tags: List): Flow