├── android └── app │ ├── .gitignore │ ├── src │ └── main │ │ ├── res │ │ ├── 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 │ │ │ ├── colors.xml │ │ │ ├── arrays.xml │ │ │ └── theme.xml │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── values-night │ │ │ └── theme.xml │ │ └── drawable │ │ │ ├── ic_indeterminate_check_box_24dp.xml │ │ │ ├── ic_highlight_24dp.xml │ │ │ ├── ic_check_box_24dp.xml │ │ │ ├── ic_error_outline_24dp.xml │ │ │ ├── ic_palette_24dp.xml │ │ │ └── ic_menu.xml │ │ ├── kotlin │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── androidapp │ │ │ ├── themes │ │ │ ├── Shape.kt │ │ │ ├── Color.kt │ │ │ ├── Type.kt │ │ │ └── Theme.kt │ │ │ ├── ColorMasterApplication.kt │ │ │ ├── routes.kt │ │ │ ├── components │ │ │ ├── atoms │ │ │ │ ├── DrawerHeader.kt │ │ │ │ ├── Tab.kt │ │ │ │ ├── DrawerButton.kt │ │ │ │ └── ColorItemContent.kt │ │ │ ├── molecules │ │ │ │ └── ScrollableTabs.kt │ │ │ └── organisms │ │ │ │ └── StaticColorLists.kt │ │ │ └── pages │ │ │ └── activity │ │ │ └── HomeActivity.kt │ │ └── AndroidManifest.xml │ ├── proguard-rules.pro │ ├── build.gradle.kts │ └── google-services.json ├── .dockerignore ├── core ├── common │ ├── src │ │ ├── androidMain │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── common │ │ │ │ ├── extensions │ │ │ │ └── AndroidColor.kt │ │ │ │ └── ui │ │ │ │ └── AndroidAppPreference.kt │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── common │ │ │ │ ├── ui │ │ │ │ ├── ThemeType.kt │ │ │ │ ├── Languages.kt │ │ │ │ └── AppPreference.kt │ │ │ │ ├── LocalKoinApp.kt │ │ │ │ └── model │ │ │ │ └── LoadState.kt │ │ ├── jsMain │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── common │ │ │ │ ├── external │ │ │ │ ├── Function.kt │ │ │ │ └── CommonJs.kt │ │ │ │ └── firebase.kt │ │ └── commonTest │ │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── common │ │ │ └── DateNumSpec.kt │ └── build.gradle.kts ├── data │ ├── src │ │ ├── androidMain │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── data │ │ │ │ ├── di │ │ │ │ └── AuthRepositories.android.kt │ │ │ │ └── DefaultAuthRepository.android.kt │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── data │ │ │ │ ├── di │ │ │ │ ├── AuthRepositories.kt │ │ │ │ ├── LiveRepositories.kt │ │ │ │ ├── PreviewRepositories.kt │ │ │ │ ├── MyIdolsRepositories.kt │ │ │ │ ├── IdolColorsRepositories.kt │ │ │ │ └── DataModule.kt │ │ │ │ ├── extension │ │ │ │ ├── ImasparqlClient.kt │ │ │ │ └── Converter.kt │ │ │ │ ├── DefaultAuthRepository.kt │ │ │ │ ├── DefaultPreviewRepository.kt │ │ │ │ ├── DefaultLiveRepository.kt │ │ │ │ └── DefaultMyIdolsRepository.kt │ │ ├── commonTest │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── data │ │ │ │ ├── extension │ │ │ │ ├── AuthClient.kt │ │ │ │ └── UserDocument.kt │ │ │ │ ├── mock │ │ │ │ ├── headers.kt │ │ │ │ ├── MockIdolSearchApi.kt │ │ │ │ └── MockSuggestLiveApi.kt │ │ │ │ └── module │ │ │ │ ├── LiveRepositoryModule.kt │ │ │ │ ├── AuthRepositoryModule.kt │ │ │ │ ├── PreviewRepositoryModule.kt │ │ │ │ ├── MyIdolsRepositoryModule.kt │ │ │ │ └── IdolColorsRepositoryModule.kt │ │ ├── jsTest │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── data │ │ │ │ ├── extension │ │ │ │ ├── AuthClient.js.kt │ │ │ │ └── UserDocument.js.kt │ │ │ │ └── spec │ │ │ │ └── DefaultAuthRepositorySpec.js.kt │ │ ├── androidUnitTest │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── data │ │ │ │ ├── extension │ │ │ │ ├── AuthClient.android.kt │ │ │ │ └── UserDocument.android.kt │ │ │ │ └── spec │ │ │ │ └── DefaultAuthRepositorySpec.android.kt │ │ └── jsMain │ │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── data │ │ │ ├── di │ │ │ └── AuthRepositories.js.kt │ │ │ └── DefaultAuthRepository.js.kt │ └── build.gradle.kts ├── model │ ├── src │ │ ├── androidMain │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── model │ │ │ │ └── auth │ │ │ │ └── AuthRepository.android.kt │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── model │ │ │ │ ├── auth │ │ │ │ ├── AuthRepository.kt │ │ │ │ ├── CredentialProvider.kt │ │ │ │ └── CurrentUser.kt │ │ │ │ ├── MyIdolsRepository.kt │ │ │ │ ├── PreviewRepository.kt │ │ │ │ ├── LiveRepository.kt │ │ │ │ ├── Inlines.kt │ │ │ │ ├── Types.kt │ │ │ │ ├── Brands.kt │ │ │ │ ├── IdolColor.kt │ │ │ │ └── IdolColorsRepository.kt │ │ └── jsMain │ │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── model │ │ │ └── auth │ │ │ └── AuthRepository.js.kt │ └── build.gradle.kts ├── test │ ├── src │ │ ├── androidMain │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── test │ │ │ │ └── fake │ │ │ │ └── FakeAuthClient.android.kt │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── test │ │ │ │ ├── MockHttpClient.kt │ │ │ │ ├── model │ │ │ │ └── CurrentUser.kt │ │ │ │ ├── data │ │ │ │ └── FirebaseUser.kt │ │ │ │ ├── fake │ │ │ │ ├── FakeAuthClient.kt │ │ │ │ └── FakeFirestoreClient.kt │ │ │ │ └── extension │ │ │ │ └── Flow.kt │ │ └── jsMain │ │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── test │ │ │ └── fake │ │ │ └── FakeAuthClient.js.kt │ └── build.gradle.kts ├── features │ ├── home │ │ ├── src │ │ │ ├── androidMain │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── kotlin │ │ │ │ │ └── net │ │ │ │ │ └── subroh0508 │ │ │ │ │ └── colormaster │ │ │ │ │ └── features │ │ │ │ │ └── home │ │ │ │ │ ├── viewmodel │ │ │ │ │ └── AuthViewModel.android.kt │ │ │ │ │ └── AndroidSignInUseCase.kt │ │ │ ├── commonMain │ │ │ │ └── kotlin │ │ │ │ │ └── net │ │ │ │ │ └── subroh0508 │ │ │ │ │ └── colormaster │ │ │ │ │ └── features │ │ │ │ │ └── home │ │ │ │ │ ├── viewmodel │ │ │ │ │ ├── AuthViewModel.kt │ │ │ │ │ ├── AuthUiState.kt │ │ │ │ │ └── CommonAuthViewModel.kt │ │ │ │ │ ├── SignInUseCase.kt │ │ │ │ │ └── SignOutUseCase.kt │ │ │ └── jsMain │ │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── features │ │ │ │ └── home │ │ │ │ ├── viewmodel │ │ │ │ └── AuthViewModel.js.kt │ │ │ │ ├── SubscribeCurrentUserUseCase.kt │ │ │ │ └── JsSignInUseCase.kt │ │ └── build.gradle.kts │ ├── myidols │ │ ├── src │ │ │ ├── androidMain │ │ │ │ └── AndroidManifest.xml │ │ │ └── commonMain │ │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── features │ │ │ │ └── myidols │ │ │ │ └── viewmodel │ │ │ │ ├── MyIdolsUiState.kt │ │ │ │ └── MyIdolsViewModel.kt │ │ └── build.gradle.kts │ ├── preview │ │ ├── src │ │ │ ├── androidMain │ │ │ │ └── AndroidManifest.xml │ │ │ └── commonMain │ │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── features │ │ │ │ └── preview │ │ │ │ ├── viewmodel │ │ │ │ ├── PenlightUiState.kt │ │ │ │ └── PenlightViewModel.kt │ │ │ │ └── FetchIdolsUseCase.kt │ │ └── build.gradle.kts │ └── search │ │ ├── src │ │ ├── androidMain │ │ │ ├── AndroidManifest.xml │ │ │ ├── res │ │ │ │ └── values │ │ │ │ │ └── strings.xml │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── features │ │ │ │ └── search │ │ │ │ └── model │ │ │ │ └── SearchByTab.kt │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── features │ │ │ │ └── search │ │ │ │ ├── model │ │ │ │ ├── SearchByTab.kt │ │ │ │ ├── SearchState.kt │ │ │ │ └── LiveNameQuery.kt │ │ │ │ └── viewmodel │ │ │ │ ├── SuggestLiveNameUiState.kt │ │ │ │ ├── SearchIdolsUiState.kt │ │ │ │ └── SuggestLiveNameViewModel.kt │ │ └── jsMain │ │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── features │ │ │ └── search │ │ │ └── model │ │ │ └── SearchByTab.kt │ │ └── build.gradle.kts └── network │ ├── auth │ ├── src │ │ ├── androidMain │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── network │ │ │ │ └── auth │ │ │ │ ├── AuthClient.android.kt │ │ │ │ └── internal │ │ │ │ └── AuthClientImpl.android.kt │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── net │ │ │ │ └── subroh0508 │ │ │ │ └── colormaster │ │ │ │ └── network │ │ │ │ └── auth │ │ │ │ ├── model │ │ │ │ ├── FirebaseUser.kt │ │ │ │ └── Provider.kt │ │ │ │ ├── di │ │ │ │ └── Auth.kt │ │ │ │ └── AuthClient.kt │ │ └── jsMain │ │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── network │ │ │ └── auth │ │ │ └── AuthClient.js.kt │ └── build.gradle.kts │ ├── firestore │ ├── src │ │ ├── androidMain │ │ │ └── AndroidManifest.xml │ │ └── commonMain │ │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── network │ │ │ └── firestore │ │ │ ├── collections.kt │ │ │ ├── document │ │ │ └── UserDocument.kt │ │ │ ├── FirestoreClient.kt │ │ │ ├── di │ │ │ └── Firestore.kt │ │ │ └── internal │ │ │ └── FirestoreClientImpl.kt │ └── build.gradle.kts │ └── imasparql │ ├── src │ ├── androidMain │ │ ├── AndroidManifest.xml │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── network │ │ │ └── imasparql │ │ │ ├── internal │ │ │ ├── AndroidURLEncoder.kt │ │ │ └── AndroidConstants.kt │ │ │ └── di │ │ │ └── AndroidHttpClient.kt │ ├── commonMain │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── network │ │ │ └── imasparql │ │ │ ├── CommonConstants.kt │ │ │ ├── internal │ │ │ ├── URLEncoder.kt │ │ │ ├── ContentType.kt │ │ │ ├── CommonConstants.kt │ │ │ └── ImasparqlApiClient.kt │ │ │ ├── json │ │ │ ├── LiveNameJson.kt │ │ │ └── IdolColorJson.kt │ │ │ ├── ImasparqlClient.kt │ │ │ ├── serializer │ │ │ └── Response.kt │ │ │ ├── query │ │ │ ├── SuggestLiveQuery.kt │ │ │ ├── RandomQuery.kt │ │ │ ├── SearchByIdQuery.kt │ │ │ ├── SearchByLiveQuery.kt │ │ │ ├── ImasparqlQuery.kt │ │ │ └── SearchByNameQuery.kt │ │ │ └── di │ │ │ └── Api.kt │ └── jsMain │ │ └── kotlin │ │ └── net │ │ └── subroh0508 │ │ └── colormaster │ │ └── network │ │ └── imasparql │ │ ├── internal │ │ └── JsURLEncoder.kt │ │ └── di │ │ └── JsHttpClient.kt │ └── build.gradle.kts ├── .firebaserc ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── js ├── app │ ├── webpack.config.d │ │ ├── 01.resources.js │ │ ├── 00.path.js │ │ ├── 04.devServer.js │ │ ├── 02.sass.js │ │ └── 03.constants.js │ └── src │ │ └── jsMain │ │ ├── resources │ │ └── sign_in_with_google.png │ │ └── kotlin │ │ ├── utilities │ │ ├── events.kt │ │ ├── mobile.kt │ │ ├── constants.kt │ │ ├── ResizeObserver.kt │ │ ├── Error.kt │ │ └── decompose.kt │ │ ├── components │ │ ├── atoms │ │ │ ├── tooltip │ │ │ │ └── Tooltip.kt │ │ │ ├── topappbar │ │ │ │ └── TopAppActionIcon.kt │ │ │ ├── chip │ │ │ │ └── ChipGroup.kt │ │ │ ├── checkbox │ │ │ │ └── CheckBoxGroup.kt │ │ │ ├── textfield │ │ │ │ ├── DebouncedTextForm.kt │ │ │ │ └── OutlinedTextField.kt │ │ │ ├── menu │ │ │ │ └── MenuButton.kt │ │ │ └── list │ │ │ │ └── ListGroupSubHeader.kt │ │ ├── organisms │ │ │ ├── list │ │ │ │ └── common.kt │ │ │ ├── drawer │ │ │ │ └── DrawerHeader.kt │ │ │ └── box │ │ │ │ └── form │ │ │ │ └── BrandForm.kt │ │ ├── molecules │ │ │ ├── TopAppBar.kt │ │ │ └── icon │ │ │ │ └── ActionIcons.kt │ │ └── templates │ │ │ └── Routing.kt │ │ ├── page │ │ ├── MyIdolsPage.kt │ │ ├── about │ │ │ ├── TermsPage.kt │ │ │ └── DevelopmentPage.kt │ │ └── SearchIdolPage.kt │ │ └── main.kt └── material │ └── src │ └── jsMain │ └── kotlin │ └── material │ ├── externals │ ├── MDCTab.kt │ ├── MDCList.kt │ ├── MDCTabBar.kt │ ├── MDCTextField.kt │ ├── MDCMenu.kt │ ├── MDCTopAppBar.kt │ ├── MDCTextFieldIcon.kt │ ├── MDCTooltip.kt │ ├── MDCDrawer.kt │ ├── MDCFormField.kt │ ├── MDCRipple.kt │ └── MDCCheckbox.kt │ ├── utilities │ ├── TagElementBuilder.kt │ └── MediaQuery.kt │ └── components │ ├── Ripple.kt │ ├── Tooltip.kt │ ├── Icon.kt │ ├── Menu.kt │ └── Card.kt ├── renovate.json ├── .gitignore ├── gradle.properties ├── plugins ├── settings.gradle.kts └── src │ └── main │ └── kotlin │ └── net │ └── subroh0508 │ └── colormaster │ ├── primitive │ ├── compose │ │ └── ComposeDsl.kt │ ├── android │ │ ├── Android.kt │ │ └── AndroidDsl.kt │ └── kmp │ │ ├── KmpDsl.kt │ │ ├── KmpJsPlugin.kt │ │ ├── KmpAndroidPlugin.kt │ │ └── KmpPlugin.kt │ ├── VersionCatalogDsl.kt │ └── convention │ ├── ModelModulePlugin.kt │ ├── ApiModulePlugin.kt │ ├── DataModulePlugin.kt │ ├── AndroidAppModulePlugin.kt │ └── CommonModulePlugin.kt ├── backend ├── cli │ ├── src │ │ └── main │ │ │ └── kotlin │ │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── backend │ │ │ └── cli │ │ │ └── imasparql │ │ │ ├── URLEncoder.kt │ │ │ ├── Constants.kt │ │ │ ├── ImasparqlClient.kt │ │ │ ├── json │ │ │ └── IdolColorJson.kt │ │ │ ├── serializer │ │ │ └── Response.kt │ │ │ ├── ImasparqlApiClient.kt │ │ │ └── query │ │ │ └── ImasparqlQuery.kt │ └── build.gradle.kts └── server │ ├── src │ └── main │ │ ├── resources │ │ └── logback.xml │ │ ├── kotlin │ │ └── net │ │ │ └── subroh0508 │ │ │ └── colormaster │ │ │ └── backend │ │ │ └── model │ │ │ └── IdolDto.kt │ │ └── sqldelight │ │ └── net │ │ └── subroh0508 │ │ └── colormaster │ │ └── backend │ │ └── database │ │ └── Idol.sq │ ├── README.md │ └── build.gradle.kts ├── firebase.json ├── .github └── workflows │ └── web-build-and-deploy.yml ├── Dockerfile └── settings.gradle.kts /android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build 3 | *.db 4 | data/ 5 | -------------------------------------------------------------------------------- /core/common/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/data/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/model/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/test/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/features/home/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/features/myidols/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/features/preview/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/features/search/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/network/auth/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/network/firestore/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /core/network/imasparql/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "imas-colormaster" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /js/app/webpack.config.d/01.resources.js: -------------------------------------------------------------------------------- 1 | config.resolve.modules.unshift(path.resolve(webAppPath, 'build/processedResources/js/main')); 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /core/model/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("colormaster.convention.model") 3 | } 4 | 5 | android { namespace = "net.subroh0508.colormaster.model" } 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /js/app/src/jsMain/resources/sign_in_with_google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/js/app/src/jsMain/resources/sign_in_with_google.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /core/features/home/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("colormaster.convention.feature") 3 | } 4 | 5 | android { namespace = "net.subroh0508.colormaster.features.home" } 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subroh0508/colormaster/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /core/features/myidols/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("colormaster.convention.feature") 3 | } 4 | 5 | android { namespace = "net.subroh0508.colormaster.features.myidols" } 6 | -------------------------------------------------------------------------------- /core/features/preview/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("colormaster.convention.feature") 3 | } 4 | 5 | android { namespace = "net.subroh0508.colormaster.features.preview" } 6 | -------------------------------------------------------------------------------- /core/features/search/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("colormaster.convention.feature") 3 | } 4 | 5 | android { namespace = "net.subroh0508.colormaster.features.search" } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.db 3 | .gradle 4 | .idea 5 | .kotlin 6 | /local.properties 7 | .DS_Store 8 | build 9 | /public 10 | /captures 11 | .externalNativeBuild 12 | /node_modules 13 | -------------------------------------------------------------------------------- /core/common/src/commonMain/kotlin/net/subroh0508/colormaster/common/ui/ThemeType.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.common.ui 2 | 3 | enum class ThemeType { 4 | DAY, NIGHT 5 | } 6 | -------------------------------------------------------------------------------- /core/features/search/src/androidMain/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | アイドル名 3 | 公演名 4 | 5 | -------------------------------------------------------------------------------- /js/app/src/jsMain/kotlin/utilities/events.kt: -------------------------------------------------------------------------------- 1 | package utilities 2 | 3 | import org.w3c.dom.HTMLInputElement 4 | import org.w3c.dom.events.Event 5 | 6 | fun Event.inputTarget() = target as HTMLInputElement 7 | -------------------------------------------------------------------------------- /core/network/imasparql/src/commonMain/kotlin/net/subroh0508/colormaster/network/imasparql/CommonConstants.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql 2 | 3 | const val HOSTNAME = "sparql.crssnky.xyz" 4 | -------------------------------------------------------------------------------- /js/app/src/jsMain/kotlin/utilities/mobile.kt: -------------------------------------------------------------------------------- 1 | package utilities 2 | 3 | import kotlinx.browser.window 4 | 5 | val isMobile: Boolean get() = """(iPhone|iPad|Android)""".toRegex().matches(window.navigator.userAgent) 6 | -------------------------------------------------------------------------------- /core/network/firestore/src/commonMain/kotlin/net/subroh0508/colormaster/network/firestore/collections.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.firestore 2 | 3 | internal const val COLLECTION_USERS = "users" 4 | 5 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xms2048m -Xmx4096m 2 | 3 | kotlin.code.style=official 4 | 5 | android.useAndroidX=true 6 | android.enableJetifier=true 7 | 8 | org.jetbrains.compose.experimental.jscanvas.enabled=true 9 | -------------------------------------------------------------------------------- /core/features/home/src/commonMain/kotlin/net/subroh0508/colormaster/features/home/viewmodel/AuthViewModel.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.features.home.viewmodel 2 | 3 | expect class AuthViewModel : CommonAuthViewModel 4 | -------------------------------------------------------------------------------- /core/features/search/src/commonMain/kotlin/net/subroh0508/colormaster/features/search/model/SearchByTab.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.features.search.model 2 | 3 | expect enum class SearchByTab { 4 | BY_NAME, BY_LIVE 5 | } 6 | -------------------------------------------------------------------------------- /core/features/search/src/commonMain/kotlin/net/subroh0508/colormaster/features/search/model/SearchState.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.features.search.model 2 | 3 | enum class SearchState { 4 | RANDOM, SEARCHED, WAITING, ERROR 5 | } 6 | -------------------------------------------------------------------------------- /core/data/src/commonMain/kotlin/net/subroh0508/colormaster/data/di/AuthRepositories.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.di 2 | 3 | import org.koin.core.module.Module 4 | 5 | expect object AuthRepositories { 6 | val Module: Module 7 | } 8 | -------------------------------------------------------------------------------- /core/network/auth/src/commonMain/kotlin/net/subroh0508/colormaster/network/auth/model/FirebaseUser.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.auth.model 2 | 3 | data class FirebaseUser( 4 | val uid: String, 5 | val providers: List, 6 | ) 7 | -------------------------------------------------------------------------------- /core/network/imasparql/src/commonMain/kotlin/net/subroh0508/colormaster/network/imasparql/internal/URLEncoder.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql.internal 2 | 3 | internal expect object URLEncoder { 4 | fun encode(s: String): String 5 | } 6 | -------------------------------------------------------------------------------- /js/app/webpack.config.d/00.path.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const rootPath = path.resolve(__dirname, '../../../../') 4 | 5 | const webAppPath = path.resolve(rootPath, 'js/app'); 6 | const nodeModulePath = path.resolve(rootPath, 'build/js/node_modules'); 7 | -------------------------------------------------------------------------------- /core/common/src/androidMain/kotlin/net/subroh0508/colormaster/common/extensions/AndroidColor.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.common.extensions 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | fun Triple.toColor() = let { (r, g, b) -> Color(r, g, b) } 6 | -------------------------------------------------------------------------------- /core/data/src/commonTest/kotlin/net/subroh0508/colormaster/data/extension/AuthClient.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.extension 2 | 3 | import net.subroh0508.colormaster.network.auth.AuthClient 4 | 5 | expect suspend fun signInWithGoogle( 6 | client: AuthClient, 7 | ) 8 | -------------------------------------------------------------------------------- /plugins/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | repositories { 3 | mavenCentral() 4 | } 5 | 6 | versionCatalogs { 7 | create("libs") { 8 | from(files("../gradle/libs.versions.toml")) 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/cli/src/main/kotlin/net/subroh0508/colormaster/backend/cli/imasparql/URLEncoder.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.backend.cli.imasparql 2 | 3 | import java.net.URLEncoder 4 | 5 | object URLEncoder { 6 | fun encode(s: String): String = URLEncoder.encode(s, "UTF-8") 7 | } 8 | -------------------------------------------------------------------------------- /js/app/src/jsMain/kotlin/components/atoms/tooltip/Tooltip.kt: -------------------------------------------------------------------------------- 1 | package components.atoms.tooltip 2 | 3 | import androidx.compose.runtime.Composable 4 | import material.components.Tooltip as MaterialTooltip 5 | 6 | @Composable 7 | fun Tooltip(id: String, text: String) = MaterialTooltip(id, text, 0L, 0L) 8 | -------------------------------------------------------------------------------- /core/data/src/jsTest/kotlin/net/subroh0508/colormaster/data/extension/AuthClient.js.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.extension 2 | 3 | import net.subroh0508.colormaster.network.auth.AuthClient 4 | 5 | actual suspend fun signInWithGoogle( 6 | client: AuthClient, 7 | ) = client.signInWithGoogle() 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /backend/cli/src/main/kotlin/net/subroh0508/colormaster/backend/cli/imasparql/Constants.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.backend.cli.imasparql 2 | 3 | const val HOSTNAME = "sparql.crssnky.xyz" 4 | const val APP_NAME = "ColorM@ster" 5 | const val ESCAPED_ENDPOINT_RDFS_DETAIL = """https://$HOSTNAME/imasrdf/RDFs/detail/""" 6 | -------------------------------------------------------------------------------- /core/model/src/commonMain/kotlin/net/subroh0508/colormaster/model/auth/AuthRepository.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.model.auth 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | 5 | expect interface AuthRepository { 6 | fun getCurrentUserStream(): Flow 7 | 8 | suspend fun signOut() 9 | } 10 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffcc80 4 | 5 | #bf360c 6 | 7 | #121212 8 | #FAFAFA 9 | 10 | -------------------------------------------------------------------------------- /core/data/src/androidUnitTest/kotlin/net/subroh0508/colormaster/data/extension/AuthClient.android.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.extension 2 | 3 | import net.subroh0508.colormaster.network.auth.AuthClient 4 | 5 | actual suspend fun signInWithGoogle( 6 | client: AuthClient, 7 | ) = client.signInWithGoogle("idToken") 8 | -------------------------------------------------------------------------------- /core/network/imasparql/src/commonMain/kotlin/net/subroh0508/colormaster/network/imasparql/json/LiveNameJson.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql.json 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class LiveNameJson internal constructor( 7 | val name: Map, 8 | ) 9 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /core/network/imasparql/src/androidMain/kotlin/net/subroh0508/colormaster/network/imasparql/internal/AndroidURLEncoder.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql.internal 2 | 3 | import java.net.URLEncoder 4 | 5 | internal actual object URLEncoder { 6 | actual fun encode(s: String): String = URLEncoder.encode(s, "UTF-8") 7 | } 8 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /js/app/src/jsMain/kotlin/components/organisms/list/common.kt: -------------------------------------------------------------------------------- 1 | package components.organisms.list 2 | 3 | const val GRID_MIN_WIDTH = 216 4 | const val GRID_MARGIN_HORIZONTAL = 8 5 | 6 | fun buildSelections( 7 | selections: List, 8 | id: String, 9 | selected: Boolean, 10 | ) = if (selected) selections + id else selections - id 11 | -------------------------------------------------------------------------------- /core/data/src/commonTest/kotlin/net/subroh0508/colormaster/data/mock/headers.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.mock 2 | 3 | import io.ktor.http.* 4 | import net.subroh0508.colormaster.network.imasparql.internal.ContentType 5 | 6 | internal val headers = headersOf( 7 | "Content-Type" to listOf(ContentType.Application.SparqlJson.toString()) 8 | ) 9 | -------------------------------------------------------------------------------- /core/network/imasparql/src/jsMain/kotlin/net/subroh0508/colormaster/network/imasparql/internal/JsURLEncoder.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql.internal 2 | 3 | private external fun encodeURIComponent(s: String): String 4 | 5 | internal actual object URLEncoder { 6 | actual fun encode(s: String): String = encodeURIComponent(s) 7 | } 8 | -------------------------------------------------------------------------------- /plugins/src/main/kotlin/net/subroh0508/colormaster/primitive/compose/ComposeDsl.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.primitive.compose 2 | 3 | import org.gradle.api.Project 4 | import org.gradle.kotlin.dsl.get 5 | import org.jetbrains.compose.ComposeExtension 6 | 7 | val Project.compose: ComposeExtension 8 | get() = extensions["compose"] as ComposeExtension 9 | -------------------------------------------------------------------------------- /core/model/src/commonMain/kotlin/net/subroh0508/colormaster/model/MyIdolsRepository.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.model 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | 5 | interface MyIdolsRepository { 6 | fun getInChargeOfIdolsStream(lang: String): Flow> 7 | 8 | fun getFavoriteIdolsStream(lang: String): Flow> 9 | } 10 | -------------------------------------------------------------------------------- /core/model/src/commonMain/kotlin/net/subroh0508/colormaster/model/PreviewRepository.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.model 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | 5 | interface PreviewRepository { 6 | fun getPreviewColorsStream(): Flow> 7 | 8 | fun clear() 9 | 10 | suspend fun show(ids: List, lang: String) 11 | } 12 | -------------------------------------------------------------------------------- /core/model/src/commonMain/kotlin/net/subroh0508/colormaster/model/auth/CredentialProvider.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.model.auth 2 | 3 | sealed class CredentialProvider { 4 | data object Anonymous : CredentialProvider() 5 | data class Google(val email: String) : CredentialProvider() 6 | data class Twitter(val displayName: String) : CredentialProvider() 7 | } 8 | -------------------------------------------------------------------------------- /core/network/imasparql/src/commonMain/kotlin/net/subroh0508/colormaster/network/imasparql/internal/ContentType.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql.internal 2 | 3 | import io.ktor.http.ContentType 4 | 5 | abstract class ContentType { 6 | object Application { 7 | val SparqlJson = ContentType("application", "sparql-results+json") 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /core/network/firestore/src/commonMain/kotlin/net/subroh0508/colormaster/network/firestore/document/UserDocument.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.firestore.document 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class UserDocument( 7 | val inCharges: List = listOf(), 8 | val favorites: List = listOf(), 9 | ) 10 | -------------------------------------------------------------------------------- /core/network/imasparql/src/commonMain/kotlin/net/subroh0508/colormaster/network/imasparql/internal/CommonConstants.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql.internal 2 | 3 | import net.subroh0508.colormaster.network.imasparql.HOSTNAME 4 | 5 | internal const val APP_NAME = "ColorM@ster" 6 | internal const val ESCAPED_ENDPOINT_RDFS_DETAIL = """https://$HOSTNAME/imasrdf/RDFs/detail/""" 7 | -------------------------------------------------------------------------------- /core/test/src/commonMain/kotlin/net/subroh0508/colormaster/test/MockHttpClient.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.test 2 | 3 | import io.ktor.client.* 4 | import io.ktor.client.engine.mock.* 5 | import io.ktor.client.request.* 6 | 7 | fun mockHttpClient( 8 | handler: MockRequestHandler = { respondOk() }, 9 | ) = HttpClient(MockEngine) { 10 | engine { addHandler(handler) } 11 | } 12 | -------------------------------------------------------------------------------- /core/features/home/src/commonMain/kotlin/net/subroh0508/colormaster/features/home/viewmodel/AuthUiState.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.features.home.viewmodel 2 | 3 | import net.subroh0508.colormaster.model.auth.CurrentUser 4 | 5 | sealed interface AuthUiState { 6 | data object NotSignedIn : AuthUiState 7 | data class SignedIn( 8 | val user: CurrentUser, 9 | ) : AuthUiState 10 | } 11 | -------------------------------------------------------------------------------- /core/network/firestore/src/commonMain/kotlin/net/subroh0508/colormaster/network/firestore/FirestoreClient.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.firestore 2 | 3 | import net.subroh0508.colormaster.network.firestore.document.UserDocument 4 | 5 | interface FirestoreClient { 6 | suspend fun setUserDocument(uid: String, userDocument: UserDocument) 7 | suspend fun getUserDocument(uid: String?): UserDocument 8 | } 9 | -------------------------------------------------------------------------------- /core/network/imasparql/src/commonMain/kotlin/net/subroh0508/colormaster/network/imasparql/json/IdolColorJson.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql.json 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class IdolColorJson internal constructor( 7 | val id: Map, 8 | val name: Map, 9 | val color: Map 10 | ) 11 | -------------------------------------------------------------------------------- /core/model/src/jsMain/kotlin/net/subroh0508/colormaster/model/auth/AuthRepository.js.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.model.auth 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | 5 | actual interface AuthRepository { 6 | actual fun getCurrentUserStream(): Flow 7 | actual suspend fun signOut() 8 | 9 | suspend fun signInWithGoogle() 10 | suspend fun signInWithGoogleForMobile() 11 | } 12 | -------------------------------------------------------------------------------- /js/material/src/jsMain/kotlin/material/externals/MDCTab.kt: -------------------------------------------------------------------------------- 1 | package material.externals 2 | 3 | import org.w3c.dom.Element 4 | 5 | @JsModule("@material/tab") 6 | @JsNonModule 7 | private external object MDCTabModule { 8 | class MDCTab(root: Element?) : material.externals.MDCTab 9 | } 10 | 11 | external interface MDCTab 12 | 13 | @Suppress("FunctionName") 14 | fun MDCTab(root: Element?): MDCTab = MDCTabModule.MDCTab(root) 15 | -------------------------------------------------------------------------------- /core/features/search/src/androidMain/kotlin/net/subroh0508/colormaster/features/search/model/SearchByTab.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.features.search.model 2 | 3 | import androidx.annotation.StringRes 4 | import net.subroh0508.colormaster.features.search.R 5 | 6 | actual enum class SearchByTab(@StringRes val labelRes: Int) { 7 | BY_NAME(R.string.search_by_tab_name), 8 | BY_LIVE(R.string.search_by_tab_live), 9 | } 10 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "public", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | }, 16 | "emulators": { 17 | "hosting": { 18 | "port": 8081, 19 | "host": "0.0.0.0" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /js/app/webpack.config.d/04.devServer.js: -------------------------------------------------------------------------------- 1 | if (config.mode === 'development') { 2 | config.devServer.historyApiFallback = true; 3 | config.devServer.host = '0.0.0.0'; 4 | config.devServer.allowedHosts = 'all'; 5 | 6 | // @see: https://github.com/JetBrains/kotlin/commit/9baa24e626b48ccfaacbf5724f58337cd29e80ab 7 | config.devServer.static = config.devServer.contentBase 8 | delete config.devServer.contentBase 9 | } 10 | -------------------------------------------------------------------------------- /core/features/home/src/androidMain/kotlin/net/subroh0508/colormaster/features/home/viewmodel/AuthViewModel.android.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.features.home.viewmodel 2 | 3 | import net.subroh0508.colormaster.model.auth.AuthRepository 4 | 5 | actual class AuthViewModel( 6 | repository: AuthRepository, 7 | ) : CommonAuthViewModel(repository) { 8 | suspend fun signInWithGoogle(idToken: String) = repository.signInWithGoogle(idToken) 9 | } -------------------------------------------------------------------------------- /js/material/src/jsMain/kotlin/material/externals/MDCList.kt: -------------------------------------------------------------------------------- 1 | package material.externals 2 | 3 | import org.w3c.dom.Element 4 | 5 | @JsModule("@material/list") 6 | @JsNonModule 7 | private external object MDCListModule { 8 | class MDCList(root: Element?) : material.externals.MDCList 9 | } 10 | 11 | external interface MDCList 12 | 13 | @Suppress("FunctionName") 14 | fun MDCList(root: Element?): MDCList = MDCListModule.MDCList(root) 15 | -------------------------------------------------------------------------------- /backend/cli/src/main/kotlin/net/subroh0508/colormaster/backend/cli/imasparql/ImasparqlClient.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.backend.cli.imasparql 2 | 3 | import kotlinx.serialization.KSerializer 4 | import net.subroh0508.colormaster.backend.cli.imasparql.serializer.Response 5 | 6 | interface ImasparqlClient { 7 | suspend fun search( 8 | query: String, 9 | serializer: KSerializer, 10 | ): Response 11 | } 12 | -------------------------------------------------------------------------------- /core/data/src/commonMain/kotlin/net/subroh0508/colormaster/data/di/LiveRepositories.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.di 2 | 3 | import net.subroh0508.colormaster.data.DefaultLiveRepository 4 | import net.subroh0508.colormaster.model.LiveRepository 5 | import org.koin.dsl.module 6 | 7 | object LiveRepositories { 8 | val Module get() = module { 9 | single { DefaultLiveRepository(get()) } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /js/app/src/jsMain/kotlin/utilities/constants.kt: -------------------------------------------------------------------------------- 1 | package utilities 2 | 3 | external val APP_NAME: String 4 | external val APP_VERSION: String 5 | external val API_KEY: String 6 | external val AUTH_DOMAIN: String 7 | external val DATABASE_URL: String 8 | external val PROJECT_ID: String 9 | external val STORAGE_BUCKET: String 10 | external val MESSAGING_SENDER_ID: String 11 | external val APP_ID: String 12 | external val MEASUREMENT_ID: String 13 | -------------------------------------------------------------------------------- /core/common/src/commonMain/kotlin/net/subroh0508/colormaster/common/LocalKoinApp.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.common 2 | 3 | import androidx.compose.runtime.Composable 4 | import androidx.compose.runtime.compositionLocalOf 5 | import org.koin.dsl.koinApplication 6 | 7 | val koinApp = koinApplication { } 8 | 9 | val LocalKoinApp = compositionLocalOf { koinApp } 10 | 11 | @Composable 12 | fun CurrentLocalKoinApp() = LocalKoinApp.current 13 | -------------------------------------------------------------------------------- /core/model/src/androidMain/kotlin/net/subroh0508/colormaster/model/auth/AuthRepository.android.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.model.auth 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | 5 | actual interface AuthRepository { 6 | actual fun getCurrentUserStream(): Flow 7 | actual suspend fun signOut() 8 | 9 | suspend fun fetchCurrentUser(): CurrentUser? 10 | suspend fun signInWithGoogle(idToken: String) 11 | } 12 | -------------------------------------------------------------------------------- /core/model/src/commonMain/kotlin/net/subroh0508/colormaster/model/LiveRepository.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.model 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | 5 | interface LiveRepository { 6 | fun getLiveNamesStream(): Flow> 7 | 8 | suspend fun refresh() 9 | 10 | suspend fun suggest(dateRange: Pair): List 11 | 12 | suspend fun suggest(name: String?): List 13 | } 14 | -------------------------------------------------------------------------------- /core/network/imasparql/src/commonMain/kotlin/net/subroh0508/colormaster/network/imasparql/ImasparqlClient.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql 2 | 3 | import kotlinx.serialization.KSerializer 4 | import net.subroh0508.colormaster.network.imasparql.serializer.Response 5 | 6 | interface ImasparqlClient { 7 | suspend fun search( 8 | query: String, 9 | serializer: KSerializer, 10 | ): Response 11 | } 12 | -------------------------------------------------------------------------------- /core/network/imasparql/src/androidMain/kotlin/net/subroh0508/colormaster/network/imasparql/internal/AndroidConstants.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.imasparql.internal 2 | 3 | import android.os.Build 4 | import net.subroh0508.colormaster.network.imasparql.BuildConfig 5 | import java.util.* 6 | 7 | internal val UserAgent = "$APP_NAME/${BuildConfig.VERSION_CODE} (Android ${Build.VERSION.SDK_INT}; ${Locale.getDefault().language}; ${Build.PRODUCT})" 8 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/net/subroh0508/colormaster/androidapp/themes/Shape.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.androidapp.themes 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) 12 | -------------------------------------------------------------------------------- /core/data/src/commonMain/kotlin/net/subroh0508/colormaster/data/di/PreviewRepositories.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.di 2 | 3 | import net.subroh0508.colormaster.data.DefaultPreviewRepository 4 | import net.subroh0508.colormaster.model.PreviewRepository 5 | import org.koin.dsl.module 6 | 7 | object PreviewRepositories { 8 | val Module get() = module { 9 | single { DefaultPreviewRepository(get()) } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /js/material/src/jsMain/kotlin/material/externals/MDCTabBar.kt: -------------------------------------------------------------------------------- 1 | package material.externals 2 | 3 | import org.w3c.dom.Element 4 | 5 | @JsModule("@material/tab-bar") 6 | @JsNonModule 7 | private external object MDCTabBarModule { 8 | class MDCTabBar(root: Element?) : material.externals.MDCTabBar 9 | } 10 | 11 | external interface MDCTabBar 12 | 13 | @Suppress("FunctionName") 14 | fun MDCTabBar(root: Element?): MDCTabBar = MDCTabBarModule.MDCTabBar(root) 15 | -------------------------------------------------------------------------------- /core/features/preview/src/commonMain/kotlin/net/subroh0508/colormaster/features/preview/viewmodel/PenlightUiState.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.features.preview.viewmodel 2 | 3 | import net.subroh0508.colormaster.model.IdolColor 4 | 5 | sealed interface PenlightUiState { 6 | data object Loading : PenlightUiState 7 | data class Loaded( 8 | val idols: List, 9 | val withDescription: Boolean, 10 | ) : PenlightUiState 11 | } -------------------------------------------------------------------------------- /backend/server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /core/data/src/commonMain/kotlin/net/subroh0508/colormaster/data/di/MyIdolsRepositories.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.di 2 | 3 | import net.subroh0508.colormaster.data.DefaultMyIdolsRepository 4 | import net.subroh0508.colormaster.model.MyIdolsRepository 5 | import org.koin.dsl.module 6 | 7 | object MyIdolsRepositories { 8 | val Module get() = module { 9 | single { DefaultMyIdolsRepository(get(), get(), get()) } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core/test/src/commonMain/kotlin/net/subroh0508/colormaster/test/model/CurrentUser.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.test.model 2 | 3 | import net.subroh0508.colormaster.model.auth.CredentialProvider 4 | import net.subroh0508.colormaster.model.auth.CurrentUser 5 | import net.subroh0508.colormaster.test.data.fromGoogle 6 | 7 | val GoogleUser = CurrentUser( 8 | fromGoogle.uid, 9 | listOf(CredentialProvider.Google(fromGoogle.providers.first().email ?: "")), 10 | ) 11 | -------------------------------------------------------------------------------- /core/common/src/commonMain/kotlin/net/subroh0508/colormaster/common/ui/Languages.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.common.ui 2 | 3 | enum class Languages(val code: String, val label: String) { 4 | JAPANESE("ja", "日本語"), 5 | ENGLISH("en", "ENGLISH"); 6 | 7 | operator fun component1() = code 8 | operator fun component2() = label 9 | 10 | companion object { 11 | fun valueOfCode(code: String) = values().find { it.code == code } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /backend/server/README.md: -------------------------------------------------------------------------------- 1 | # COLOR M@STER バックエンドモジュール 2 | 3 | このモジュールは、COLOR M@STERアプリケーションのバックエンドサーバーを提供します。 4 | 5 | ## 機能 6 | 7 | - REST APIエンドポイント 8 | - SQLiteデータベース連携 9 | - ビジネスロジック処理 10 | 11 | ## 技術スタック 12 | 13 | - Ktor: サーバーフレームワーク 14 | - SQLDelight: タイプセーフなSQLクエリ 15 | - Kotlinx Serialization: JSONシリアライゼーション 16 | - Kotlinx Coroutines: 非同期処理 17 | - Logback: ロギング 18 | - Docker: コンテナ化 19 | 20 | ## 開発方法 21 | 22 | ### ローカルでのサーバー起動 23 | 24 | ```bash 25 | ./gradlew :backend:run 26 | -------------------------------------------------------------------------------- /core/data/src/commonTest/kotlin/net/subroh0508/colormaster/data/extension/UserDocument.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.extension 2 | 3 | import net.subroh0508.colormaster.network.auth.AuthClient 4 | import net.subroh0508.colormaster.network.firestore.FirestoreClient 5 | 6 | expect suspend fun setUserDocument( 7 | auth: AuthClient, 8 | firestore: FirestoreClient, 9 | inChargeIds: List = listOf(), 10 | favoriteIds: List = listOf(), 11 | ) 12 | -------------------------------------------------------------------------------- /core/network/auth/src/commonMain/kotlin/net/subroh0508/colormaster/network/auth/model/Provider.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.auth.model 2 | 3 | data class Provider( 4 | val id: String, 5 | val email: String?, 6 | val displayName: String?, 7 | ) { 8 | companion object { 9 | const val PROVIDER_ANONYMOUS = "anonymous" 10 | const val PROVIDER_GOOGLE = "google.com" 11 | const val PROVIDER_TWITTER = "twitter.com" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /js/material/src/jsMain/kotlin/material/externals/MDCTextField.kt: -------------------------------------------------------------------------------- 1 | package material.externals 2 | 3 | import org.w3c.dom.Element 4 | 5 | @JsModule("@material/textfield") 6 | @JsNonModule 7 | private external object MDCTextFieldModule { 8 | class MDCTextField(root: Element?): material.externals.MDCTextField 9 | } 10 | 11 | external interface MDCTextField 12 | 13 | @Suppress("FunctionName") 14 | fun MDCTextField(root: Element?): MDCTextField = MDCTextFieldModule.MDCTextField(root) 15 | -------------------------------------------------------------------------------- /core/data/src/commonMain/kotlin/net/subroh0508/colormaster/data/di/IdolColorsRepositories.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.data.di 2 | 3 | import net.subroh0508.colormaster.data.DefaultIdolColorsRepository 4 | import net.subroh0508.colormaster.model.IdolColorsRepository 5 | import org.koin.dsl.module 6 | 7 | object IdolColorsRepositories { 8 | val Module get() = module { 9 | single { DefaultIdolColorsRepository(get(), get(), get()) } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core/network/auth/src/commonMain/kotlin/net/subroh0508/colormaster/network/auth/di/Auth.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.network.auth.di 2 | 3 | import dev.gitlive.firebase.Firebase 4 | import dev.gitlive.firebase.auth.auth 5 | import net.subroh0508.colormaster.network.auth.AuthClient 6 | import org.koin.core.module.Module 7 | import org.koin.dsl.module 8 | 9 | object Auth { 10 | val Module: Module get() = module { 11 | single { AuthClient(Firebase.auth) } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /core/features/search/src/jsMain/kotlin/net/subroh0508/colormaster/features/search/model/SearchByTab.kt: -------------------------------------------------------------------------------- 1 | package net.subroh0508.colormaster.features.search.model 2 | 3 | actual enum class SearchByTab( 4 | val query: String, 5 | val labelKey: String, 6 | ) { 7 | BY_NAME("", "searchBox.tabs.name"), 8 | BY_LIVE("live", "searchBox.tabs.live"); 9 | 10 | companion object { 11 | fun findByQuery(query: String?) = values().find { it.query == query } ?: BY_NAME 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/theme.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 8 | 9 | 15 | 16 |